Skip to content

Commit b751818

Browse files
kodemaniakmuuki88
authored andcommitted
RpmNoReplaceplugin and LinuxMappingDSL for "noreplace" configs (#896)
* First try at #572. Config files from the `universal/conf` directory are correctly marked as `noconfig`, but `/etc/default` files provided by JavaServerApp archetype not. * Added a RpmConfigNoReplacePlugin that depends on the Rpm and ServerAppPackaging plugins. It marks all config files as "noreplace" in the RPM, thus preventing them from being replaced during updates. The main method was added to the LinuxMappingDSL and can also be used in build.sbt for non server projects. * Fixed formatting. * Removed RpmConfigNoReplace plugin in favour of the DSL. Added docs for the DSL.
1 parent 7ca19fd commit b751818

File tree

12 files changed

+115
-10
lines changed

12 files changed

+115
-10
lines changed

src/main/scala/com/typesafe/sbt/packager/linux/LinuxMappingDSL.scala

+16
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ trait LinuxMappingDSL {
3232
(src, dest) <- dirs
3333
path <- (src ***).get
3434
} yield path -> path.toString.replaceFirst(src.toString, dest)
35+
36+
/**
37+
* This method sets the config attribute of all files that are marked as configuration files to "noreplace". This is
38+
* relevant for RPM packages as it controls the behaviour of RPM updates.
39+
*
40+
* See: http://www-uxsup.csx.cam.ac.uk/~jw35/docs/rpm_config.html
41+
*
42+
* @param mappings list of mappings to update
43+
* @return updated list of mappings
44+
*/
45+
def configWithNoReplace(mappings: Seq[LinuxPackageMapping]): Seq[LinuxPackageMapping] = {
46+
mappings.map {
47+
case mapping if mapping.fileData.config != "false" => mapping.withConfig("noreplace")
48+
case mapping => mapping
49+
}
50+
}
3551
}
3652

3753
object Mapper extends LinuxMappingDSL
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
enablePlugins(RpmPlugin)
2+
3+
name := "rpm-test"
4+
5+
version := "0.1.0"
6+
7+
maintainer := "Josh Suereth <[email protected]>"
8+
9+
packageSummary := "Test rpm package"
10+
11+
packageDescription := """A fun package description of our software,
12+
with multiple lines."""
13+
14+
rpmRelease := "1"
15+
16+
rpmVendor := "typesafe"
17+
18+
rpmUrl := Some("http://github.com/sbt/sbt-native-packager")
19+
20+
rpmLicense := Some("BSD")
21+
22+
packageArchitecture in Rpm := "x86_64"
23+
24+
linuxPackageMappings := configWithNoReplace(linuxPackageMappings.value)
25+
26+
TaskKey[Unit]("unzip") <<= (packageBin in Rpm, streams) map { (rpmFile, streams) =>
27+
val rpmPath = Seq(rpmFile.getAbsolutePath)
28+
Process("rpm2cpio", rpmPath) #| Process("cpio -i --make-directories") ! streams.log
29+
}
30+
31+
TaskKey[Unit]("checkSpecFile") <<= (target, streams) map { (target, out) =>
32+
val spec = IO.read(target / "rpm" / "SPECS" / "rpm-test.spec")
33+
34+
assert(
35+
spec contains
36+
"%files\n%dir %attr(0755,root,root) /usr/share/rpm-test/conf",
37+
"Contains configuration directory."
38+
)
39+
40+
assert(
41+
spec contains
42+
"%config(noreplace) %attr(0644,root,root) /usr/share/rpm-test/conf/test",
43+
"Sets custom config to 'noreplace'"
44+
)
45+
46+
out.log.success("Successfully tested rpm test file")
47+
()
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Test configuration file!
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Run the debian packaging.
2+
> rpm:package-bin
3+
$ exists target/rpm/RPMS/x86_64/rpm-test-0.1.0-1.x86_64.rpm
4+
5+
> unzip
6+
7+
> checkSpecFile

src/sbt-test/rpm/override-start-script-systemd/build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ TaskKey[Unit]("checkStartupScript") <<= (target, streams) map { (target, out) =>
3333
val script = IO.read(file("usr/lib/systemd/system/rpm-test.service"))
3434
assert(script.startsWith("# right systemd template"), s"override script wasn't picked, script is\n$script")
3535
()
36-
}
36+
}

src/sbt-test/rpm/override-start-script-systemv/build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ TaskKey[Unit]("checkStartupScript") <<= (target, streams) map { (target, out) =>
3333
val script = IO.read(file("etc/init.d/rpm-test"))
3434
assert(script.startsWith("# right systemv template"), s"override script wasn't picked, script is\n$script")
3535
()
36-
}
36+
}

src/sbt-test/rpm/override-start-script-upstart/build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ TaskKey[Unit]("checkStartupScript") <<= (target, streams) map { (target, out) =>
3333
val script = IO.read(file("etc/init/rpm-test.conf"))
3434
assert(script.startsWith("# right upstart template"), s"override script wasn't picked, script is\n$script")
3535
()
36-
}
36+
}

src/sphinx/formats/rpm.rst

+15
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,18 @@ For more information on this topic follow these links:
359359
.. _OpenSuse issue: https://github.com/sbt/sbt-native-packager/issues/215
360360
.. _RPM Scaladocs: http://www.scala-sbt.org/sbt-native-packager/latest/api/#com.typesafe.sbt.packager.rpm.RpmPlugin$$Names$
361361
.. _MaintainerScriptHelper Scaladocs: http://www.scala-sbt.org/sbt-native-packager/latest/api/#com.typesafe.sbt.packager.MaintainerScriptHelper$
362+
363+
364+
Marking config files as ``noreplace``
365+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
366+
367+
By default, rpm replaces config files on disk when the content has changed between two version. Often, this is not desirable
368+
as configurations are often customized and should not change during updates. rpm provides a means to turn of the default behaviour
369+
by marking config files as ``noreplace`` in the spec file. In order to enable this for the build, we provide a helper method that
370+
can be used to modify all config file mappings:
371+
372+
.. code-block:: scala
373+
374+
linuxPackageMappings := configWithNoReplace(linuxPackageMappings.value)
375+
376+
This will mark all config files as ``noreplace`` and prevent them from being changed during updates.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.typesafe.sbt.packager.linux
2+
3+
import java.io.File
4+
5+
import org.scalatest.{Matchers, WordSpec}
6+
7+
class LinuxMappingDSLSpec extends WordSpec with Matchers with LinuxMappingDSL {
8+
9+
"The LinuxMappingDSL" should {
10+
11+
"map config files to noreplace" in {
12+
val f1 = LinuxPackageMapping(Map(new File("/tmp/1") -> "/tmp/1"))
13+
val f2 = LinuxPackageMapping(Map(new File("/tmp/1") -> "/tmp/1")).withConfig()
14+
15+
val f1Mapped :: f2Mapped :: Nil = configWithNoReplace(Seq(f1, f2))
16+
17+
f1Mapped.fileData.config should be("false")
18+
f2Mapped.fileData.config should be("noreplace")
19+
}
20+
}
21+
}

src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala

+2-6
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@ import com.typesafe.sbt.packager._
44
import com.typesafe.sbt.packager.permissions
55
import org.scalatest._
66
import java.io.File
7-
import java.nio.file.{Path, Paths, Files}
7+
import java.nio.file.{Files, Path, Paths}
88
import java.nio.file.attribute.PosixFilePermission._
99
import scala.collection.JavaConversions._
1010

11-
class ZipHelperSpec
12-
extends WordSpec
13-
with Matchers
14-
with BeforeAndAfterEach
15-
with BeforeAndAfterAll {
11+
class ZipHelperSpec extends WordSpec with Matchers with BeforeAndAfterEach with BeforeAndAfterAll {
1612

1713
var tmp: Path = _
1814
val toDelete = scala.collection.mutable.ListBuffer[Path]()

version.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version in ThisBuild := "1.2.0-SNAPSHOT"
1+
version in ThisBuild := "1.2.0-SNAPSHOT"

0 commit comments

Comments
 (0)