Skip to content

Commit

Permalink
Fixes #7207: Select and display agent mode (verify/enforce)
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelGauthier committed Oct 7, 2016
1 parent 71a5bfe commit 9859b6b
Show file tree
Hide file tree
Showing 37 changed files with 2,363 additions and 612 deletions.
Expand Up @@ -44,6 +44,7 @@ import com.normation.rudder.reports.AgentRunInterval
import com.normation.rudder.reports.HeartbeatConfiguration
import net.liftweb.common._
import com.normation.inventory.domain.NodeId
import com.normation.rudder.domain.policies.PolicyMode

/**
* Node Repository
Expand Down
Expand Up @@ -50,6 +50,7 @@ import com.normation.rudder.reports.AgentRunInterval
import com.normation.rudder.reports.HeartbeatConfiguration
import net.liftweb.common._
import com.normation.rudder.repository.EventLogRepository
import com.normation.rudder.domain.policies.PolicyMode

class WoLDAPNodeRepository(
nodeDit : NodeDit
Expand Down
8 changes: 5 additions & 3 deletions rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala
Expand Up @@ -387,7 +387,7 @@ object RudderConfig extends Loggable {
val reportsRepository : ReportsRepository = reportsRepositoryImpl
val eventLogDeploymentService: EventLogDeploymentService = eventLogDeploymentServiceImpl
val allBootstrapChecks : BootstrapChecks = allChecks
lazy val srvGrid = new SrvGrid(roAgentRunsRepository, asyncComplianceService)
lazy val srvGrid = new SrvGrid(roAgentRunsRepository, asyncComplianceService, configService)
val findExpectedReportRepository : FindExpectedReportRepository = findExpectedRepo
val historizationRepository : HistorizationRepository = historizationJdbcRepository
val roApiAccountRepository : RoApiAccountRepository = roLDAPApiAccountRepository
Expand Down Expand Up @@ -1117,7 +1117,7 @@ object RudderConfig extends Loggable {
, diffRepos
, PendingInventory
)
private[this] lazy val nodeGridImpl = new NodeGrid(ldapFullInventoryRepository, nodeInfoServiceImpl)
private[this] lazy val nodeGridImpl = new NodeGrid(ldapFullInventoryRepository, nodeInfoServiceImpl, configService)

private[this] lazy val modificationService = new ModificationService(logRepository,gitModificationRepository,itemArchiveManagerImpl,uuidGen)
private[this] lazy val eventListDisplayerImpl = new EventListDisplayer(
Expand Down Expand Up @@ -1748,7 +1748,9 @@ object RudderConfig extends Loggable {
roLdapRuleRepository
, roLdapDirectiveRepository
, reportingServiceImpl
, techniqueRepositoryImpl)
, techniqueRepositoryImpl
, configService
)
private[this] lazy val propertyRepository = new RudderPropertiesSquerylRepository(
squerylDatasourceProvider
, reportsRepository )
Expand Down
@@ -0,0 +1,33 @@
package com.normation.rudder.web.components

import net.liftweb.http.DispatchSnippet
import net.liftweb.common._
import net.liftweb.http.{SHtml,S}
import scala.xml._
import net.liftweb.http.js._
import JsCmds._
import JE._
import net.liftweb.util.Helpers
import net.liftweb.util.Helpers._
import net.liftweb.http.Templates

class AgentPolicyModeEditForm extends DispatchSnippet with Loggable {

// Html template
def templatePath = List("templates-hidden", "components", "ComponentAgentPolicyMode")
def template() = Templates(templatePath) match {
case Empty | Failure(_,_,_) =>
sys.error("Template for Agent Policy Mode configuration not found. I was looking for %s.html"
.format(templatePath.mkString("/")))
case Full(n) => n
}
def agentPolicyModeTemplate = chooseTemplate("agentpolicymode", "form", template)

def dispatch = {
case "cfagentPolicyModeConfiguration" => (xml) => cfagentPolicyModeConfiguration
}

def cfagentPolicyModeConfiguration = {
agentPolicyModeTemplate ++ Script(OnLoad(JsRaw("angular.bootstrap('#auditMode', ['auditmode']);")))
}
}
Expand Up @@ -212,9 +212,9 @@ class ComplianceModeEditForm [T <: ComplianceMode] (
s"""
angular.bootstrap("#complianceMode", ['complianceMode']);
var scope = angular.element($$("#complianceModeController")).scope();
scope.$$apply(function(){
scope.init(${toJs(complianceMode)}, ${toJs(globalMode)}, ${isNodePage} ,${callback.toJsCmd}, "${S.contextPath}", ${allModes});
} );
scope.$$apply(function(){
scope.init(${toJs(complianceMode)}, ${toJs(globalMode)}, ${isNodePage} ,${callback.toJsCmd}, "${S.contextPath}", ${allModes});
});
"""
}) match {
case eb:EmptyBox =>
Expand Down
Expand Up @@ -68,6 +68,10 @@ import com.normation.cfclerk.domain.TechniqueName
import com.normation.rudder.web.components.popup.ModificationValidationPopup
import com.normation.cfclerk.domain.TechniqueId
import com.normation.cfclerk.domain.TechniqueVersion
import com.normation.rudder.web.rest.node.SettingsAPI8
import com.normation.rudder.web.rest.node.SettingsApi
import com.normation.rudder.domain.policies.PolicyMode.Verify
import com.normation.rudder.domain.policies.PolicyMode.Enforce

object DirectiveEditForm {

Expand Down Expand Up @@ -100,17 +104,18 @@ object DirectiveEditForm {
* Parameters can not be null.
*/
class DirectiveEditForm(
htmlId_policyConf : String
, technique : Technique
, activeTechnique : ActiveTechnique
, fullActiveTechnique : FullActiveTechnique
, val directive : Directive
, oldDirective : Option[Directive]
, workflowEnabled : Boolean
, onSuccessCallback : (Either[Directive,ChangeRequestId]) => JsCmd = { (Directive) => Noop }
, onMigrationCallback : (Directive, Option[Directive]) => JsCmd
, onFailureCallback : () => JsCmd = { () => Noop }
, isADirectiveCreation : Boolean = false
htmlId_policyConf : String
, technique : Technique
, activeTechnique : ActiveTechnique
, fullActiveTechnique : FullActiveTechnique
, val directive : Directive
, oldDirective : Option[Directive]
, workflowEnabled : Boolean
, globalMode : GlobalPolicyMode
, onSuccessCallback : (Either[Directive,ChangeRequestId]) => JsCmd = { (Directive) => Noop }
, onMigrationCallback : (Directive, Option[Directive]) => JsCmd
, onFailureCallback : () => JsCmd = { () => Noop }
, isADirectiveCreation : Boolean = false
, onRemoveSuccessCallBack : () => JsCmd = { () => Noop }
) extends DispatchSnippet with Loggable {

Expand All @@ -122,21 +127,22 @@ class DirectiveEditForm(
private[this] val woChangeRequestRepo = RudderConfig.woChangeRequestRepository
private[this] val roChangeRequestRepo = RudderConfig.roChangeRequestRepository
private[this] val techniqueRepo = RudderConfig.techniqueRepository
private[this] val roRuleRepo = RudderConfig.roRuleRepository
private[this] val roRuleCategoryRepo = RudderConfig.roRuleCategoryRepository
private[this] val roRuleRepo = RudderConfig.roRuleRepository
private[this] val roRuleCategoryRepo = RudderConfig.roRuleCategoryRepository
private[this] val configService = RudderConfig.configService

private[this] val htmlId_save = htmlId_policyConf + "Save"
private[this] val parameterEditor = {
directiveEditorService.get(technique.id, directive.id, directive.parameters) match {
case Full(pe) => pe
case Empty => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). No error returned"
"(template %s). No error returned"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id))
}
case Failure(m, _, _) => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). Error message: %s"
"(template %s). Error message: %s"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id, m))
}
}
Expand Down Expand Up @@ -207,7 +213,7 @@ class DirectiveEditForm(
val agentCompEmpty : NodeSeq =
<span>
Can be used on any agent.
</span>
</span>
technique.compatible match {
case None =>
(osCompEmpty,agentCompEmpty)
Expand All @@ -226,7 +232,7 @@ class DirectiveEditForm(
case agent =>
<span>
{agent.mkString(", ")}
</span>
</span>
}
(osComp,agentComp)
}
Expand Down Expand Up @@ -272,6 +278,7 @@ class DirectiveEditForm(
"#shortDescriptionField" #> piShortDescription.toForm_! &
"#longDescriptionField" #> piLongDescription.toForm_! &
"#priority" #> piPriority.toForm_! &
"#policyModes" #> policyModes.toForm_! &
"#version" #> versionSelect.toForm_! &
"#migrate" #> migrateButton(directiveVersion.is,"Migrate") &
"#parameters" #> parameterEditor.toFormNodeSeq &
Expand Down Expand Up @@ -396,28 +403,25 @@ class DirectiveEditForm(

private[this] val piPriority =
new WBSelectObjField(
"Priority:"
"Priority"
, (0 to 10).map(i => (i, i.toString))
, defaultValue = directive.priority
) {
override val displayHtml =
<div>
<b>Priority:</b>
<span class="tw-bs">
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="priorityId">
<h4> Priority </h4>
Priority determines which <b> unique </b> Directive will be applied.
<br/>
Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.
<br/>
Highest Priority is 0
</div>
</span>
</div>
<b>Priority</b>
<span class="tw-bs">
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="priorityId">
<h4> Priority </h4>
<p>Priority determines which <b> unique </b> Directive will be applied.</p>
<p>Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.</p>
<p>Highest Priority is 0.</p>
</div>
</span>
</div>
override def className = "twoCol"
override def labelClassName = "threeCol directiveInfo"

}

def showDeprecatedVersion (version : TechniqueVersion) = {
Expand All @@ -427,6 +431,55 @@ class DirectiveEditForm(
}
s"${version} ${deprecationInfo}"
}
private[this] val globalOverrideText = configService.rudder_policy_overridable().getOrElse("") match {
case true =>
<div>
You may override the agent policy mode on this directive.
If set to <b>Audit</b> this directive will never be enforced.
If set to <b>Enforce</b> this directive will appply necessary changes except on Nodes with a <b>Verify</b> override setting.
</div>
case false =>
<p>
Currrent global settings do not allow this mode to be overriden on a per-directive bases. You may change this in <b>Settings</b>,
or contact your Rudder administrator about this.
</p>
}
private[this] val policyModes = {
val globalPolicyModeName = configService.rudder_policy_mode_name().getOrElse("error").toString
val policyName = directive.policyMode match {
case None => globalPolicyModeName
case _ => directive.policyMode.getOrElse("error").toString
}
val l = Seq(None -> s"Use global default mode (currently ${globalPolicyModeName})", Some(Enforce) -> "Override to Enforce", Some(Verify) -> "Override to Audit")
new WBSelectObjField(
"Policy mode"
, l
, defaultValue = directive.policyMode
) {
override val displayHtml =
<div>
<b>Policy mode</b>
<span class="tw-bs">
<span tooltipid="policyModeId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="policyModeId">
<h4>Policy mode</h4>
<p>Configuration rules in Rudder can operate in one of two modes:</p>
<ol>
<li><b>Audit</b>: the agent will examine configurations and report any differences, but will not make any changes</li>
<li><b>Enforce</b>: the agent will make changes to fix any configurations that differ from your directives</li>
</ol>
<p>
By default all nodes and all directives operate in the global default mode defined in
<b> Settings</b>, which is currently <b>{globalPolicyModeName}</b>.
</p>
{globalOverrideText}
</div>
</span>
</div>
override def className = "twoCol"
override def labelClassName = "threeCol directiveInfo"
}
}

val versions = fullActiveTechnique.techniques.keys.map(v => (v,showDeprecatedVersion(v))).toSeq.sortBy(_._1)

Expand Down Expand Up @@ -487,12 +540,13 @@ class DirectiveEditForm(
}

val newDirective = directive.copy(
parameters = parameterEditor.mapValueSeq
, name = piName.is
parameters = parameterEditor.mapValueSeq
, name = piName.is
, shortDescription = piShortDescription.is
, priority = piPriority.is
, longDescription = piLongDescription.is
, _isEnabled = directive.isEnabled
, priority = piPriority.is
, longDescription = piLongDescription.is
, _isEnabled = directive.isEnabled
, policyMode = policyModes.is
)

displayConfirmationPopup(
Expand All @@ -506,11 +560,13 @@ class DirectiveEditForm(
val isMigration = oldDirective.map( _.techniqueVersion != directive.techniqueVersion).getOrElse(false)

val updatedDirective = directive.copy(
parameters = parameterEditor.mapValueSeq,
name = piName.is,
shortDescription = piShortDescription.is,
priority = piPriority.is,
longDescription = piLongDescription.is)
parameters = parameterEditor.mapValueSeq
, name = piName.is
, shortDescription = piShortDescription.is
, priority = piPriority.is
, longDescription = piLongDescription.is
, policyMode = policyModes.is
)

if ((!isMigration && directive == updatedDirective && updatedRules.isEmpty)) {
onNothingToDo()
Expand Down
Expand Up @@ -89,6 +89,7 @@ class RuleCompliance (
private[this] val reportingService = RudderConfig.reportingService
private[this] val recentChangesService = RudderConfig.recentChangesService
private[this] val categoryService = RudderConfig.ruleCategoryService
private[this] val configService = RudderConfig.configService

//fresh value when refresh
private[this] val roRuleRepository = RudderConfig.roRuleRepository
Expand Down Expand Up @@ -154,7 +155,7 @@ class RuleCompliance (
function refresh() {${refresh().toJsCmd}};
createDirectiveTable(true, false, "${S.contextPath}")("reportsGrid",[],refresh);
createNodeComplianceTable("nodeReportsGrid",[],"${S.contextPath}", refresh);
createChangesTable("changesGrid",[],"${S.contextPath}");
createChangesTable("changesGrid",[],"${S.contextPath}", refresh);
correctButtons();
refresh();
""")))
Expand Down Expand Up @@ -293,10 +294,11 @@ class RuleCompliance (
updatedRule <- roRuleRepository.get(rule.id)
directiveLib <- getFullDirectiveLib()
allNodeInfos <- getAllNodeInfos()
globalMode <- configService.rudder_global_policy_mode()
} yield {

val directiveData = ComplianceData.getRuleByDirectivesComplianceDetails(reports, updatedRule, allNodeInfos, directiveLib).json.toJsCmd
val nodeData = ComplianceData.getRuleByNodeComplianceDetails(directiveLib, reports, allNodeInfos).json.toJsCmd
val directiveData = ComplianceData.getRuleByDirectivesComplianceDetails(reports, updatedRule, allNodeInfos, directiveLib, globalMode).json.toJsCmd
val nodeData = ComplianceData.getRuleByNodeComplianceDetails(directiveLib, reports, allNodeInfos, globalMode).json.toJsCmd
JsRaw(s"""
refreshTable("reportsGrid", ${directiveData});
refreshTable("nodeReportsGrid", ${nodeData});
Expand Down

0 comments on commit 9859b6b

Please sign in to comment.