All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nebula.plugin.ospackage.daemon.OspackageDaemonPlugin.groovy Maven / Gradle / Ivy

There is a newer version: 3.1.1
Show newest version
/*
 * Copyright 2014 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nebula.plugin.ospackage.daemon

import com.netflix.gradle.plugins.packaging.SystemPackagingBasePlugin
import com.netflix.gradle.plugins.packaging.SystemPackagingTask
import com.netflix.gradle.plugins.rpm.Rpm
import org.gradle.api.DomainObjectCollection
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.internal.DefaultDomainObjectCollection

class OspackageDaemonPlugin implements Plugin {
    Project project
    DaemonExtension extension

    Map toContext(DaemonDefinition definitionDefaults, DaemonDefinition definition) {
        return [
                daemonName: definition.daemonName ?: definitionDefaults.daemonName,
                command: definition.command,
                user: definition.user ?: definitionDefaults.user,
                logCommand: definition.logCommand ?: definitionDefaults.logCommand,
                runLevels: definition.runLevels ?: definitionDefaults.runLevels,
                autoStart: definition.autoStart != null? definition.autoStart : definitionDefaults.autoStart,
                startSequence: definition.startSequence ?: definitionDefaults.startSequence,
                stopSequence: definition.stopSequence ?: definitionDefaults.stopSequence
        ]
    }

    @Override
    void apply(Project project) {
        this.project = project
        project.plugins.apply(SystemPackagingBasePlugin)

        // TODO Use NamedContainerProperOrder so that we can create tasks for each definition as they appear
        DomainObjectCollection daemonsList = new DefaultDomainObjectCollection<>(DaemonDefinition, []) // project.container(DaemonDefinition)
        //List daemonsList = new LinkedList()
        extension = project.extensions.create('daemons', DaemonExtension, daemonsList)

        // Add daemon to project
        project.ext.daemon = { Closure closure ->
            extension.daemon(closure)
        }

        daemonsList.all { DaemonDefinition definition ->
            // Check existing name
            def sameName = daemonsList.any { !it.is(definition) && it.daemonName == definition.daemonName }
            if (sameName) {
                if (definition.daemonName) {
                    throw new IllegalArgumentException("A daemon with the name ${definition.daemonName} is already defined")
                } else {
                    throw new IllegalArgumentException("A daemon with no name, and hence the default, is already defined")
                }
            }

            project.tasks.withType(SystemPackagingTask) { SystemPackagingTask task ->
                def isRedhat = task instanceof Rpm
                DaemonDefinition defaults = new DaemonDefinition(null, null, 'root', 'multilog t ./main', isRedhat?[3,4,5]:[2,3,4,5], Boolean.TRUE, 85, 15)

                // Calculate daemonName really early, but everything else can be done later.
                def daemonName = definition.daemonName ?: defaults.daemonName ?: task.getPackageName()

                if (!daemonName) {
                    throw new IllegalArgumentException("Unable to find a name on definition ${definition}")
                }
                String cleanedName = daemonName.replaceAll("\\W", "").capitalize()


                def outputDir = new File(project.buildDir, "daemon/${cleanedName}/${task.name}")

                def mapping = [
                        'log-run': "/service/${daemonName}/log/run",
                        'run': "/service/${daemonName}/run",
                        'initd': isRedhat?"/etc/rc.d/init.d/${daemonName}":"/etc/init.d/${daemonName}"
                ]

                def templateTask = project.tasks.create("${task.name}${cleanedName}Daemon", DaemonTemplateTask)
                templateTask.conventionMapping.map('destDir') { outputDir }
                templateTask.conventionMapping.map('context') {
                    Map context = toContext(defaults, definition)
                    context.daemonName = daemonName
                    context.isRedhat = isRedhat
                    context
                }
                templateTask.conventionMapping.map('templates') { mapping.keySet() }

                task.dependsOn(templateTask)
                mapping.each { String templateName, String destPath ->
                    File rendered = new File(outputDir, templateName) // To be created by task, ok that it's not around yet

                    // Gradle CopySpec can't set the name of a file on the fly, we need to do a rename.
                    def slashIdx = destPath.lastIndexOf('/')
                    def destDir = destPath.substring(0,slashIdx)
                    def destFile = destPath.substring(slashIdx+1)
                    task.from(rendered) {
                        into(destDir)
                        rename('.*', destFile)
                        fileMode 0555 // Since source files don't have the correct permissions
                        user templateTask.getContext().user // TODO Confirm this is late enough
                    }
                }

                task.doFirst {
                    def startSequence = templateTask.getContext().startSequence
                    def stopSequence = templateTask.getContext().stopSequence
                    def runLevels = templateTask.getContext().runLevels

                    task.postInstall("[ -x /bin/touch ] && touch=/bin/touch || touch=/usr/bin/touch")
                    task.postInstall("\$touch /service/${daemonName}/down")

                    def installCmd = isRedhat?
                            "/sbin/chkconfig ${daemonName} on":
                            "/usr/sbin/update-rc.d ${daemonName} start ${startSequence} ${runLevels.join(' ')} . stop ${stopSequence} ${([0,1,2,3,4,5,6]-runLevels).join(' ')} ."

                    if (templateTask.getContext().autoStart) {
                        task.postInstall(installCmd)
                    }

                }
            }
        }
    }
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy