gradle-ospackage-plugin icon indicating copy to clipboard operation
gradle-ospackage-plugin copied to clipboard

How to modify rpm file listing to not manage all directories

Open cwalker67 opened this issue 10 years ago • 15 comments

I'm kind of having a hard time trying to figure out how to configure an rpm to only manage a subset of directories being installed. for example:

buildRpm {
    into('/opt/test')
    from(war.outputs.files) {
        into('warDir')
        user 'testuser'
        groupPermission 'testgroup'
    } 
}

when you copy the rpm out to a linux box and query the list of files managed shows:

rpm -qpl testwar.rpm
/opt/test
/opt/test/warDir
/opt/test/warDir/test.war

Installation will cause the /opt/test directory ownership to be testuser:testgroup even if the directory already exists. The install will also fail if the /opt/test directory is managed by another rpm with a 'file conflict' error

What I would like to see from the rpm is:

rpm -qpl testwar.rpm
/opt/test/warDir
/opt/test/warDir/test.war

But I can't figure out the correct combination of configuration to get it to work. Has anyone else ran into this?

cwalker67 avatar Oct 15 '14 20:10 cwalker67

Have you tried setting addParentDirs=false?

On Wed, Oct 15, 2014 at 1:38 PM, Charles Walker [email protected] wrote:

I'm kind of having a hard time trying to figure out how to configure an rpm to only manage a subset of directories being installed. for example:

buildRpm { into('/opt/test') from(war.outputs.files) { into('warDir') user 'testuser' groupPermission 'testgroup' } }

when you copy the rpm out to a linux box and query the list of files managed shows:

rpm -qpl testwar.rpm /opt/test /opt/test/warDir /opt/test/warDir/test.war

Installation will cause the /opt/test directory ownership to be testuser:testgroup even if the directory already exists. The install will also fail if the /opt/test directory is managed by another rpm with a 'file conflict' error

What I would like to see from the rpm is:

rpm -qpl testwar.rpm /opt/test/warDir /opt/test/warDir/test.war

But I can't figure out the correct combination of configuration to get it to work. Has anyone else ran into this?

— Reply to this email directly or view it on GitHub https://github.com/nebula-plugins/gradle-ospackage-plugin/issues/59.

quidryan avatar Oct 15 '14 20:10 quidryan

yes, and at best i ended up with something like:

rpm -qpl testwar.rpm
/opt/test/warDir/test.war

which upon removal of the rpm does not delete the /opt/test/warDir directory which ends up being owned by root

cwalker67 avatar Oct 16 '14 02:10 cwalker67

So /opt/test is considered "built-in" then on your system.

There was a recent enhancement just made to the underlying redline-rpm library that makes it safe to specify built-in directories on a per Contents basis:

https://github.com/craigwblake/redline/commit/062a56d1601ae3a030cb0e2661ae12288fca80c6

Not available as a feature within the ospackage-plugin yet, but should be straight-forward to add. Technically if you don't mind the "/opt/test" directory considered built-in for all rpm tasks within a build, you can call Contents.addBuiltinDirectory('/opt/test') currently in your build file during the configuration phase and it will do what you desire.

Maybe I'll find time to start working on gradle-related things again and enhance the gradle-ospackage-plugin with this change, but I don't believe that's going to happen in the next month or so.

merscwog avatar Oct 16 '14 10:10 merscwog

Spencer, Could you elaborate on how to call Contents.addBuiltinDirectory('/opt/test') in the current configuration?

cwalker67 avatar Oct 16 '14 11:10 cwalker67

Outside of any tasks:

import org.redline_rpm.payload.Contents Contents.addBuiltinDirectory('opt/test')

Warning. In the future, this will break with newer versions of redline-rpm (yet to be released) which remove the static method.

merscwog avatar Oct 16 '14 11:10 merscwog

Thanks spencer but i was not able to get this working (using gradle 2.0.1).

  • I changed the import to be 'org.freecompany.redline.payload.Contents' since thats what the plugin uses
  • I needed to add the redline library as a classpath dependency

At this point, i could execute the task but it seemed to be ignoring the "built in" directory i added

cwalker67 avatar Oct 16 '14 16:10 cwalker67

I wanted to elaborate a little further on this as a possible bug. take the following full example:

plugins {
    id "nebula.os-package" version "2.0.2"
}

repositories {
    mavenCentral()
}

configurations {
    test
}

dependencies {
    test 'org.apache.anakia:anakia:1.0@pom'
}

group = 'org.test.package'
version = "1.0.0"

ospackage {
    os = LINUX
    arch = NOARCH
}

task fooRpm(type: Rpm) {
    packageName 'foo'
    into('/opt/test')

    from(configurations.test.getSingleFile()) {
        user 'nobody'
        permissionGroup 'nobody'
        into('bin')
    } 
}

task barRpm(type: Rpm) {
    packageName 'bar'
    into('/opt/test')

    from(configurations.test.getSingleFile()) {
        user 'adm'
        permissionGroup 'adm'
        into('test')
    } 
}

Using gradle 2.0.1 and executing gradle clean fooRpm barRpm produces two rpms. if you try to install both packages (on a recent linux version), it will fail with a file conflict on /opt/test

Both rpms try to take ownership of /opt/test even though the above configuration doesn't seem to represent that. Adding addParentDirs=false will allow the install to occur but all directories created are then owned by root and not removed when the rpm in uninstalled

cwalker67 avatar Oct 16 '14 16:10 cwalker67

Ah. Forgot that it's using an older version of the redline classes.

This used to work in some of the gradle 1.x versions (at least 1.10 and prior).

It's possible that due to some better classloader isolation that you are seeing a different Contents class instance.

Not sure when I'll be able to look more into this, but that's my best guess without creating an example myself with a newer gradle instance.

-Spencer


From: Charles Walker [email protected] To: nebula-plugins/gradle-ospackage-plugin [email protected] Cc: Spencer Allain [email protected] Sent: Thursday, October 16, 2014 12:29 PM Subject: Re: [gradle-ospackage-plugin] How to modify rpm file listing to not manage all directories (#59)

Thanks spencer but i was not able to get this working (using gradle 2.0.1).

  • I changed the import to be 'org.freecompany.redline.payload.Contents' since thats what the plugin uses
  • I needed to add the redline library as a classpath dependency At this point, i could execute the task but it seemed to be ignoring the "built in" directory i added

— Reply to this email directly or view it on GitHub.

merscwog avatar Oct 16 '14 17:10 merscwog

Could this be escalated to "Bug" status?

cwalker67 avatar Jun 09 '15 17:06 cwalker67

@cwalker67 Could you please provide a pull request containing an integration test that reproduces the issue? We can then take it from there.

bmuschko avatar Jun 18 '15 17:06 bmuschko

I created a test which fails on the issue. I think the main issue is that there is no (easy) way to specify a directory as "built-in". while diving in, i did manage to come up with a workaround (documented in a second test) where you create all directories with the "directory" command and then specify "addParentDirs false" when copying files.

cwalker67 avatar Jul 23 '15 19:07 cwalker67

@cwalker67 Does your latest workaround (second test) handle the uninstall scenario. I have a similar issue and was using the addParentsDir false as a workaround, but the uninstall is not deleting the leaf folders? Were you able to get around that (without using the postUnistall script)?

ubhatta33 avatar Aug 03 '15 19:08 ubhatta33

@ubhatta33 Yes. The basic gist is that you use the directory command to specify ALL rpm managed directories. Then you can copy files and specify the addParentDirs false attribute. here is a (contrived) example:

Note that /opt/test/foo and it's subdirectories are the only directories managed by the rpm. if /opt/test/ does not exist, it will be created but not considered owned by the rpm

plugins {
    id "nebula.os-package" version "2.2.6"
}

repositories {
    mavenCentral()
}

configurations {
    test
}

dependencies {
    test 'org.apache.anakia:anakia:1.0@jar'
}

group = 'org.test.package'
version = "1.0.0"

ospackage {
    os = LINUX
    arch = NOARCH
}

task fooRpm(type: Rpm) {
    packageName 'foo'

    user 'nobody'
    permissionGroup 'nobody'
    directory('/opt/test/foo')

    FileTree fileTree = zipTree(configurations.test.getSingleFile()).getAsFileTree()
    fileTree.visit { FileVisitDetails fileVisitDetails ->
        if (fileVisitDetails.isDirectory()) {
            directory('/opt/test/foo/' + fileVisitDetails.relativePath)
        }
    }

    from(zipTree(configurations.test.getSingleFile())) {
        addParentDirs false
        into('/opt/test/foo')
    } 
}

rpm -qpl foo-1.0.0.noarch.rpm now properly shows

[vagrant@localhost vagrant]$ rpm -qlp foo-1.0.0.noarch.rpm
/opt/test/foo
/opt/test/foo/META-INF
/opt/test/foo/META-INF/LICENSE
/opt/test/foo/META-INF/MANIFEST.MF
/opt/test/foo/META-INF/NOTICE
/opt/test/foo/org
/opt/test/foo/org/apache
/opt/test/foo/org/apache/anakia
/opt/test/foo/org/apache/anakia/AnakiaElement.class
/opt/test/foo/org/apache/anakia/AnakiaJDOMFactory.class
/opt/test/foo/org/apache/anakia/AnakiaTask$Context.class
/opt/test/foo/org/apache/anakia/AnakiaTask.class
/opt/test/foo/org/apache/anakia/Escape.class
/opt/test/foo/org/apache/anakia/NodeList$1.class
/opt/test/foo/org/apache/anakia/NodeList$AttributeXMLOutputter.class
/opt/test/foo/org/apache/anakia/NodeList.class
/opt/test/foo/org/apache/anakia/OutputWrapper.class
/opt/test/foo/org/apache/anakia/TreeWalker.class
/opt/test/foo/org/apache/anakia/XPathCache.class
/opt/test/foo/org/apache/anakia/XPathTool.class

cwalker67 avatar Aug 07 '15 14:08 cwalker67

sorry, clicked the wrong button.

cwalker67 avatar Aug 07 '15 14:08 cwalker67

Sorry, is there solution except add all directories as builtin?

Hubbitus avatar Feb 09 '16 17:02 Hubbitus