sbt native-packager RPM install directory issue - scala

I have tried to modify the install dir of my RPM. This seems to work, however my RPM now is missing the init.d start script. When I look in target/universal/tmp/bin, I don't see systemv-init.
Below is my snippet code from my build.sbt that show how I am overriding the install directory. I have custom start script in src/templates directory for my scala fat jar app. When I remove the below install directory override, the RPM packages fine and install ok in /usr/share. Any help with this issue is greatly appreciated.
linuxPackageMappings in Rpm <<= (linuxPackageMappings) map { mappings =>
for(LinuxPackageMapping(filesAndNames, meta, zipped) <- mappings) yield {
val newFilesAndNames = for {
(file, installPath) <- filesAndNames
} yield file -> installPath.replaceFirst("/usr/share", "/opt")
LinuxPackageMapping(newFilesAndNames, meta, zipped)
}
}

I was able to solve this by removing the above code and just adding one liner to my build.sbt:
defaultLinuxInstallLocation:= "/opt"

Related

Running Wget in scala build.sbt

I have a requirement where I need to download a bunch of jars from a url and then place them inside a lib directory and then add them to unmanaged dependancy.
I am kind of stuck on how to do this in build.sbt. Went over sbt documentation and I found processbuilder. With that in mind, I came up with the below code.
for(i <- jarUrls) {
val wget = s"wget -P $libDir $anonUser#$hgRootURL/$i"
wget !
}
This runs wget on a bunch of jars and then places the file in the mentioned folder. Pretty simple code, but I am unable to run this. The error that I get is "Expression of type Unit must confirm to DslEntry in SBT file".
How to accomplish this?
build.sbt isn't just scala file, sbt does special preprocessing on it (that's why you don't have to def project = etc).
Your problem happens because every line of code (except imports and definitions) in build.sbt must return expression of type DslEntry as sbt sees every line of code as setting. When do you want your wget to get executed? usual way is to define Task:
lazy val wget = taskKey[Unit]("Wget")
wget := {
for(i <- List(1,2,3)) {
val wget = s"wget -P $libDir $anonUser#$hgRootURL/$i"
wget !
}
()
}
and run it like sbt wget.
You can also make wget task dependent on some other task (or you can think of them as events) in sbt.
See http://www.scala-sbt.org/0.13/docs/Tasks.html
Of course, there are tricky unsafe ways, like:
val init: Unit = {
//any code you want here
}
But I wouldn't recommend it since you probably want those files during let's say compile stage or something:
wget := {
your code here
} dependsOn compile
you can also use regular scala build instead of build.sbt: http://www.scala-sbt.org/0.13/docs/Full-Def.html

Couldn't package a cron job using sbt-native-packager when building a deb bundle

I am trying to package a cron as part of my debian package (https://github.com/indykish/megam_akka.git).
The debian package is built using the sbt-native-packager.
I placed the cron script inside my bin directory as here https://github.com/indykish/megam_akka/blob/master/bin/megamherk.cron.d
I changed my build.sbt to pickup the megamher.cron.d as here
https://github.com/indykish/megam_akka/blob/master/build.sbt
I have attached the snippet of code here:
linuxPackageMappings in Debian <+= (baseDirectory) map { bd =>
(packageMapping((bd / "bin/herk_stash") -> "/usr/share/megamherk/bin/herk_stash")
withUser "root" withGroup "root" withPerms "0755")
}
linuxPackageMappings in Debian <+= (baseDirectory) map { bd =>
(packageMapping((bd / "bin/megamherk.cron.d") -> "/etc/cron.d/megamherk")
withUser "root" withGroup "root" withPerms "0755")
}
I ran:
sbt clean compile
sbt dist:dist
sbt debian:packageBin
The generated debian bundle inside the target directory doesn't have the cron bundled.
I referred this debian documentation (http://www.debian.org/doc/manuals/maint-guide/dother.en.html#crond)
Am I missing something here ? How do I make sbt-native-package pickup a cron job ?
The easiest way to package simple files is to use the default directory structure.
src/linux/...
In your case you would put your file in
src/linux/etc/cron.d/megamherk
You locale settings will be reapplied. So if megamherk is executable it will stay executable.
If this doesn't work for you open a ticket with a small test case.
cheers,
Muki

config directory when using sbt-native-packager

I'd like to ask about reasoning behind the fact, that the sbt-native-packager plugin creates a symlink /etc/ -> /usr/share//conf (instead of really putting files there and somehow specifying in the app where to look for them)?
In particular how does it influence update/uninstall+install process? Are the configs somehow preserved (for example for debian with java_server architecture setting)?
I'd like to ask about reasoning behind the fact, that the sbt-native-packager plugin creates a symlink /etc/ -> /usr/share//conf
Keeping everything in one place. You have your application directory which contains everything and then you just link from the OS-specific folders to the according directories in your application folder.
Are the configs somehow preserved
Yes indeed. You can try it out with a simple play application. Add this to your build.sbt
mappings in Universal <+= (packageBin in Compile, baseDirectory ) map { (_, base) =>
val conf = base / "conf" / "application.conf"
conf -> "conf/application.conf"
}
This will map your application.conf in the conf folder. When you build a debian package with
debian:packageBin
you can see in target/-/DEBIAN/conffiles an entry
/usr/share/<app-name>/conf/application.conf
An apt-get remove your-app won't remove this file, only a purge

Modifying install directory for rpm with sbt native-packager

I am trying to build an rpm package with the sbt-native-packager that installs in a custom directory eg /opt/myapp instead of /usr - due to in-house policy requirements.
I have a build.sbt that will build a standard rpm but I'm stumped when it comes to modifying the directory. My apologies-I'm quite new to scala, sbt and the native pacakger.
I am using mapGenericFilesToLinux and would like to keep its structure - just modifying the first part of the destination directory.
I found this code fragment in a git hub issue https://github.com/sbt/sbt-native-packager/issues/4#issuecomment-6731183
linuxPackageMappings <+= target map { target =>
val src = target / "webapp"
val dest = "/opt/app"
LinuxPackageMapping(
for {
path <- (src ***).get
if !path.isDirectory
} yield path -> path.toString.replaceFirst(src.toString, dest)
)
}
I believe I want to do something similar except to
linuxPackageMappings in Rpm <++= <SOMETHING HERE> {
// for loop that steps through the source and destination and modifies the directory
}
thanks in advance for any help
bye
Pam
So, in sbt 0.12 you need to make sure you specify all the dependent keys you want to use before declaring the value you want. SO, let's pretend two things:
linuxPackageMappings has all your mappings for the packaging.
linuxPackageMappings in Rpm has nothing added to it directly.
We're going to take the value in linuxPackageMappings and alter the directory for linuxPackageMappings in Rpm:
linuxPackageMappings in Rpm <<= (linuxPackageMappings) map { mappings =>
// Let's loop through the mappings and alter their on-disc location....
for(LinuxPackageMapping(filesAndNames, meta, zipped) <- mappings) yield {
val newFilesAndNames = for {
(file, installPath) <- filesAndNames
} yield file -> installPath.replaceFirst("/usr/share/app", "/opt/app")
LinuxPackageMapping(newFilesAndNames, meta, zipped)
}
}
What this does is rip out the linux package mappings (which include whether or not to gzip files, and the user/group owners/permissions) and modify the install path of each file.
Hope that helps! IN sbt-native-packager.NEXT (not released) you can configure the default install location.

Unable to use a class from a package in /lib directory

I did a simple thing: I put a jar file I've made myself into /lib directory of a Play application. However, it doesn't work:
def index = Action {
val a = new com.mypackage.Class123 // error! not found Class123
Ok(views.html.index("hello"))
}
It already said sbt, compile, gen-idea but everything is still the same.
By the way, the file /lib/mypackage.jar is 38Mb for some reason.
Try reload in sbt. This is needed to rescan the build file; it might also be needed to rescan the lib directory (I'm not sure).