Revision d09c18c1
Added by François ARMAND over 6 years ago
pom.xml | ||
---|---|---|
<parent>
|
||
<groupId>com.normation.rudder</groupId>
|
||
<artifactId>rudder-parent</artifactId>
|
||
<version>4.1.0</version>
|
||
<version>4.2.0~rc3-SNAPSHOT</version>
|
||
</parent>
|
||
|
||
<description>
|
src/main/scala-templates/default/com/normation/plugins/datasources/EnablePluginImpl.scala | ||
---|---|---|
|
||
package com.normation.plugins.datasources
|
||
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import bootstrap.rudder.plugin.DatasourcesStatus
|
||
import com.normation.plugins.PluginStatus
|
||
import com.normation.plugins.PluginStatusInfo
|
||
|
||
/*
|
||
* The class will be loaded by ServiceLoader, it needs an empty constructor.
|
||
* unlimited version of the plugin
|
||
*/
|
||
|
||
final class CheckRudderPluginDatasourcesEnableImpl() extends CheckRudderPluginDatasourcesEnable {
|
||
val hasLicense = false
|
||
val isEnabled = true
|
||
val enabledStatus = DatasourcesStatus.Enabled
|
||
val licenseInformation = None
|
||
final class CheckRudderPluginDatasourcesEnableImpl() extends PluginStatus {
|
||
override val isEnabled = true
|
||
override val enabledStatus = PluginStatusInfo.EnabledNoLicense
|
||
}
|
||
|
src/main/scala-templates/limited/com/normation/plugins/datasources/EnablePluginImpl.scala | ||
---|---|---|
import java.util.Formatter.DateTime
|
||
import java.io.InputStreamReader
|
||
import org.joda.time.DateTime
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import bootstrap.rudder.plugin.DatasourcesStatus
|
||
import bootstrap.rudder.plugin.DatasourcesLicenseInfo
|
||
import com.normation.plugins.PluginStatus
|
||
import com.normation.plugins.PluginStatusInfo
|
||
import com.normation.plugins.PluginLicenseInfo
|
||
|
||
|
||
/*
|
||
... | ... | |
* The class will be loaded by ServiceLoader, it needs an empty constructor.
|
||
*/
|
||
|
||
final class CheckRudderPluginDatasourcesEnableImpl() extends CheckRudderPluginDatasourcesEnable {
|
||
final class CheckRudderPluginDatasourcesEnableImpl() extends PluginStatus {
|
||
// here are processed variables
|
||
val CLASSPATH_KEYFILE = "${plugin-resource-publickey}"
|
||
val FS_SIGNED_LICENSE = "${plugin-resource-license}"
|
||
val VERSION = "${plugin-declared-version}"
|
||
|
||
val maybeLicense = LicenseReader.readLicense(FS_SIGNED_LICENSE)
|
||
val hasLicense = true
|
||
|
||
// for now, we only read license info at load, because it's time consuming
|
||
val maybeInfo =
|
||
val maybeInfo = {
|
||
for {
|
||
unchecked <- maybeLicense
|
||
publicKey <- {
|
||
val key = this.getClass.getClassLoader.getResourceAsStream(CLASSPATH_KEYFILE)
|
||
if(key == null) {
|
||
Left(LicenseError.IO(s"The resources '${CLASSPATH_KEYFILE}' was not found"))
|
||
Left(LicenseError.IO(s"The classpath resources '${CLASSPATH_KEYFILE}' was not found"))
|
||
} else {
|
||
RSAKeyManagement.readPKCS8PublicKey(new InputStreamReader(key), None) //don't give to much info about path
|
||
}
|
||
... | ... | |
} yield {
|
||
(checked, version)
|
||
}
|
||
}
|
||
|
||
maybeInfo.fold( error => DataSourceLogger.error(error) , ok => DataSourceLogger.warn("License signature is valid.") )
|
||
//log at that point is we read the license information for the plugin
|
||
maybeInfo.fold( error => DataSourceLogger.error(error) , ok => DataSourceLogger.info("Plugin 'datasources' has a license and the license signature is valid.") )
|
||
|
||
def isEnabled = enabledStatus == DatasourcesStatus.Enabled
|
||
|
||
def enabledStatus: DatasourcesStatus = {
|
||
def current: PluginStatusInfo = {
|
||
(for {
|
||
info <- maybeInfo
|
||
(license, version) = info
|
||
... | ... | |
} yield {
|
||
check
|
||
}) match {
|
||
case Right(x) => DatasourcesStatus.Enabled
|
||
case Left (y) => DatasourcesStatus.Disabled(y.msg)
|
||
case Right(x) => PluginStatusInfo.EnabledWithLicense(licenseInformation(x))
|
||
case Left (y) => PluginStatusInfo.Disabled(y.msg, maybeLicense.toOption.map(licenseInformation))
|
||
}
|
||
}
|
||
|
||
def licenseInformation(): Option[DatasourcesLicenseInfo] = maybeLicense match {
|
||
case Left(_) => None
|
||
case Right(l) => Some(DatasourcesLicenseInfo(
|
||
licensee = l.content.licensee.value
|
||
, softwareId = l.content.softwareId.value
|
||
, minVersion = l.content.minVersion.value.toString
|
||
, maxVersion = l.content.maxVersion.value.toString
|
||
, startDate = l.content.startDate.value
|
||
, endDate = l.content.endDate.value
|
||
))
|
||
private[this] def licenseInformation(l: License): PluginLicenseInfo = {
|
||
PluginLicenseInfo(
|
||
licensee = l.content.licensee.value
|
||
, softwareId = l.content.softwareId.value
|
||
, minVersion = l.content.minVersion.value.toString
|
||
, maxVersion = l.content.maxVersion.value.toString
|
||
, startDate = l.content.startDate.value
|
||
, endDate = l.content.endDate.value
|
||
)
|
||
}
|
||
|
||
}
|
||
|
src/main/scala/bootstrap/rudder/plugin/EnablePlugin.scala | ||
---|---|---|
/*
|
||
*************************************************************************************
|
||
* Copyright 2017 Normation SAS
|
||
*************************************************************************************
|
||
*
|
||
* This file is part of Rudder.
|
||
*
|
||
* Rudder is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* In accordance with the terms of section 7 (7. Additional Terms.) of
|
||
* the GNU General Public License version 3, the copyright holders add
|
||
* the following Additional permissions:
|
||
* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
|
||
* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
|
||
* Public License version 3, when you create a Related Module, this
|
||
* Related Module is not considered as a part of the work and may be
|
||
* distributed under the license agreement of your choice.
|
||
* A "Related Module" means a set of sources files including their
|
||
* documentation that, without modification of the Source Code, enables
|
||
* supplementary functions or services in addition to those offered by
|
||
* the Software.
|
||
*
|
||
* Rudder is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
*
|
||
*************************************************************************************
|
||
*/
|
||
|
||
package bootstrap.rudder.plugin
|
||
|
||
import org.joda.time.DateTime
|
||
|
||
/**
|
||
* This file defined an entry point for license information and other
|
||
* enabling of the plugin
|
||
*/
|
||
|
||
sealed trait DatasourcesStatus
|
||
final object DatasourcesStatus {
|
||
final case object Enabled extends DatasourcesStatus
|
||
final case class Disabled(reason: String) extends DatasourcesStatus
|
||
}
|
||
|
||
/*
|
||
* This object gives main information about license information.
|
||
* It is destinated to be read to the user. No string information
|
||
* should be used for comparison.
|
||
*/
|
||
final case class DatasourcesLicenseInfo(
|
||
licensee : String
|
||
, softwareId: String
|
||
, minVersion: String
|
||
, maxVersion: String
|
||
, startDate : DateTime
|
||
, endDate : DateTime
|
||
)
|
||
|
||
trait CheckRudderPluginDatasourcesEnable {
|
||
|
||
/*
|
||
* Does the plugin has a license to display?
|
||
*/
|
||
def hasLicense(): Boolean
|
||
|
||
/*
|
||
* Is the plugin currently enabled (at the moment of the request)
|
||
*/
|
||
def isEnabled(): Boolean
|
||
|
||
/*
|
||
* What is the CURRENT status of the plugin at the moment of the request
|
||
*/
|
||
def enabledStatus(): DatasourcesStatus
|
||
|
||
/*
|
||
* Information about the license. Maybe none is the plugin
|
||
* is not a limited version.
|
||
*/
|
||
def licenseInformation(): Option[DatasourcesLicenseInfo]
|
||
}
|
src/main/scala/com/normation/plugins/datasources/DataSourcesPluginDef.scala | ||
---|---|---|
import net.liftweb.sitemap.Menu
|
||
import scala.xml.NodeSeq
|
||
import com.typesafe.config.ConfigFactory
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import bootstrap.rudder.plugin.DatasourcesStatus
|
||
import com.normation.plugins.PluginStatus
|
||
|
||
class DataSourcesPluginDef(info: CheckRudderPluginDatasourcesEnable) extends RudderPluginDef with Loggable {
|
||
class DataSourcesPluginDef(info: PluginStatus) extends RudderPluginDef with Loggable {
|
||
|
||
override val basePackage = "com.normation.plugins.datasources"
|
||
|
||
... | ... | |
}
|
||
|
||
override def description : NodeSeq = (
|
||
<div>
|
||
<p>
|
||
Data source plugin allows to get node properties from third parties provider accessible via a REST API.
|
||
Configuration can be done in <a href="/secure/administration/dataSourceManagement">the dedicated management page</a>
|
||
</p>
|
||
{ // license information
|
||
if(!info.hasLicense) {
|
||
NodeSeq.Empty
|
||
} else {
|
||
val (bg, msg) = info.enabledStatus() match {
|
||
case DatasourcesStatus.Enabled => ("info", None)
|
||
case DatasourcesStatus.Disabled(msg) => ("danger", Some(msg))
|
||
}
|
||
|
||
<div class="tw-bs"><div id="license-information" style="padding:5px; margin: 5px;" class={s"bs-callout bs-callout-${bg}"}>
|
||
<h4>License information</h4>
|
||
<p>This binary version of the plugin is submited to a license with the
|
||
following information:</p>
|
||
<div class={s"bg-${bg}"}>{
|
||
info.licenseInformation() match {
|
||
case None => <p>It was not possible to read information about the license.</p>
|
||
case Some(i) =>
|
||
<dl class="dl-horizontal" style="padding:5px;">
|
||
<dt>Plugin with ID</dt> <dd>{i.softwareId}</dd>
|
||
<dt>Licensee</dt> <dd>{i.licensee}</dd>
|
||
<dt>Supported version</dt> <dd>from {i.minVersion} to {i.maxVersion}</dd>
|
||
<dt>Validity period</dt> <dd>from {i.startDate.toString("YYYY-MM-dd")} to {i.endDate.toString("YYYY-MM-dd")}</dd>
|
||
</dl>
|
||
}}
|
||
{msg.map(s => <p class="text-danger">{s}</p>).getOrElse(NodeSeq.Empty)}
|
||
</div>
|
||
</div></div>
|
||
}
|
||
}
|
||
</div>
|
||
|
||
)
|
||
|
||
val status: PluginStatus = info
|
||
|
||
def init = {
|
||
PluginLogger.info(s"loading '${buildConf.getString("plugin-id")}:${version.toString}' plugin")
|
||
LiftRules.statelessDispatch.append(DatasourcesConf.dataSourceApi9)
|
src/main/scala/com/normation/plugins/datasources/Repository.scala | ||
---|---|---|
import scala.concurrent.duration._
|
||
import scalaz.{ Failure => _ }
|
||
import scalaz.Scalaz._
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import com.normation.plugins.PluginStatus
|
||
|
||
final case class PartialNodeUpdate(
|
||
nodes : Map[NodeId, NodeInfo] //the node to update
|
||
... | ... | |
backend : DataSourceRepository
|
||
, fetch : QueryDataSourceService
|
||
, uuidGen : StringUuidGenerator
|
||
, pluginStatus: CheckRudderPluginDatasourcesEnable
|
||
, pluginStatus: PluginStatus
|
||
) extends DataSourceRepository with DataSourceUpdateCallbacks {
|
||
|
||
/*
|
src/main/scala/com/normation/plugins/datasources/Scheduler.scala | ||
---|---|---|
import net.liftweb.common.Loggable
|
||
import scala.concurrent.duration.FiniteDuration
|
||
import scala.util.control.NonFatal
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import com.normation.plugins.PluginStatus
|
||
|
||
|
||
final case class UpdateCause(modId: ModificationId, actor:EventActor, reason:Option[String], triggeredByGeneration: Boolean = false)
|
||
... | ... | |
class DataSourceScheduler(
|
||
val datasource : DataSource
|
||
, implicit val scheduler : Scheduler
|
||
, pluginStatus: CheckRudderPluginDatasourcesEnable
|
||
, pluginStatus: PluginStatus
|
||
, newUuid : () => ModificationId
|
||
, updateAll : UpdateCause => Unit
|
||
) extends Loggable {
|
||
... | ... | |
scheduledTask = Some(source.subscribe())
|
||
} else {
|
||
// the plugin is disabled, does nothing
|
||
DataSourceLogger.warn(s"The datasource with id '${datasource.id.value}' is enabled but the plugin is disabled (reason: ${pluginStatus.enabledStatus}). Not scheduling future runs for it.")
|
||
DataSourceLogger.warn(s"The datasource with id '${datasource.id.value}' is enabled but the plugin is disabled (reason: ${pluginStatus.current}). Not scheduling future runs for it.")
|
||
}
|
||
} else {
|
||
DataSourceLogger.trace(s"The datasource with id '${datasource.id.value}' is disabled. Not scheduling future runs for it.")
|
src/test/scala/com/normation/plugins/datasources/UpdateHttpDatasetTest.scala | ||
---|---|---|
import scala.concurrent.ExecutionContext
|
||
import scala.concurrent.duration._
|
||
import scala.util.Random
|
||
import bootstrap.rudder.plugin.CheckRudderPluginDatasourcesEnable
|
||
import bootstrap.rudder.plugin.DatasourcesStatus
|
||
import com.normation.plugins.AlwaysEnabledPluginStatus
|
||
|
||
|
||
|
||
... | ... | |
val uuidGen = new StringUuidGeneratorImpl()
|
||
}
|
||
|
||
object Enabled extends CheckRudderPluginDatasourcesEnable {
|
||
val hasLicense = false
|
||
val isEnabled = true
|
||
val enabledStatus = DatasourcesStatus.Enabled
|
||
val licenseInformation = None
|
||
}
|
||
|
||
|
||
sequential
|
||
|
||
"Update on datasource" should {
|
||
... | ... | |
val dss = new DataSourceScheduler(
|
||
datasource.copy(enabled = false)
|
||
, testScheduler
|
||
, Enabled
|
||
, AlwaysEnabledPluginStatus
|
||
, () => ModificationId(MyDatasource.uuidGen.newUuid)
|
||
, action
|
||
)
|
||
... | ... | |
val dss = new DataSourceScheduler(
|
||
datasource.copy(runParam = datasource.runParam.copy(schedule = NoSchedule(1.second)))
|
||
, testScheduler
|
||
, Enabled
|
||
, AlwaysEnabledPluginStatus
|
||
, () => ModificationId(MyDatasource.uuidGen.newUuid)
|
||
, action
|
||
)
|
||
... | ... | |
val dss = new DataSourceScheduler(
|
||
datasource
|
||
, testScheduler
|
||
, Enabled
|
||
, AlwaysEnabledPluginStatus
|
||
, () => ModificationId(MyDatasource.uuidGen.newUuid)
|
||
, action
|
||
)
|
Also available in: Unified diff
Fixes #11429: Update datasource to Rudder 4.2 license framework