Name
sn_agent.PolicyDraftUtils
Description
No description available
Script
var PolicyDraftUtils = Class.create();
PolicyDraftUtils.prototype = {
CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD: {
"monitored_ci_type_filter": "",
"filter": "",
"table": "",
"monitored_ci_type_script": "",
"monitored_ci_script": "",
"monitored_ci_type_group": "",
"monitored_ci_group": "",
"proxy_agent": "single_proxy_agent",
"proxy_filter": "proxy_advanced",
"proxy_script": "proxy_script_advanced",
"single_proxy_agent": "",
"proxy_advanced": "",
"proxy_script_advanced": "",
"proxy_cluster": "",
"agent_cluster_name": "proxy_cluster",
"run_checks_on_all_proxyagents": "",
"is_service_filter": "",
"service_filter": "",
},
POLICY_EXCLUDED_COMPARISON_FIELDS: ['is_draft', 'publish_status', 'published_parent', 'related_policy', 'publish_error', 'checks_str'],
CHECK_EXCLUDED_COMPARISON_FIELDS: ['monitoring_policy', 'is_draft', 'published_parent', 'published_check', 'check_json', 'prev_command'],
PARAMS_EXCLUDED_COMPARISON_FIELDS: ['check', 'is_draft', 'published_parent', 'published_param', 'published_secure_param'],
initialize: function() {
this.policyStateUtil = new PolicyStateUtil();
},
getPublishedParent: function(policyDraftSysID) {
var policyGr = new GlideRecord("sn_agent_policy");
policyGr.setLimit(1);
var hasSucceed = policyGr.get(policyDraftSysID);
if (hasSucceed)
return policyGr.related_policy;
return "";
},
getRelatedPolicy: function(policySysID) {
var policyGr = new GlideRecord("sn_agent_policy");
policyGr.setLimit(1);
var hasSucceed = policyGr.get("related_policy", policySysID);
if (hasSucceed) {
return policyGr;
}
return null;
},
saveDraft: function(draftPolicyGr) {
var publishedValue = draftPolicyGr.getValue("publish_status");
var publishedPolicyId = draftPolicyGr.getValue("related_policy");
//if status was published and we have parent, change it to published*
var isPublished = (publishedValue != '0' && publishedValue != '2');
var changeStatusToPublishStar = isPublished && publishedPolicyId;
//change the status to published* on the draft copy if needed
if (changeStatusToPublishStar) {
draftPolicyGr.setValue("publish_status", "2");
}
var updatedId = draftPolicyGr.update();
// draft policy pubish status was just updated, so synchronize the publish status down to the policy state records
this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);
if (changeStatusToPublishStar) {
//only if we were able to save the draft and we need to change the status to Published*
if (updatedId != null) {
var publishedRecord = new GlideRecord("sn_agent_policy");
if (publishedRecord.get(publishedPolicyId)) {
publishedRecord.setValue("publish_status", "2");
//don't change the update time of the published policy upon the change of this status, so it will not be downloaded to mid again
publishedRecord.setWorkflow(false);
publishedRecord.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedRecord);
}
} else {
// we are here since we failed to update the draft, so that current draft form will not present Published*, restore it to Published
draftPolicyGr.setValue("publish_status", "1");
draftPolicyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);
}
}
},
/*
Clone a Policy Tree to draft or public depending on the isClonePublish value
sourcePolicyGr = the source policy to clone from
isClonePublish = Is the clone record publish or draft
clonePolicyGr = the clone policy to clone to
isDraftChild = is the tree created will be a child
*/
clonePolicyTree: function(sourcePolicyGr, isClonePublish, clonePolicyGr, isDraftChild) {
var sourcePolicyId = sourcePolicyGr.getValue("sys_id");
var createNewPolicyRecord = true;
if (!clonePolicyGr) {
clonePolicyGr = this.cloneRecord(sourcePolicyGr);
} else {
this.cloneRecord(sourcePolicyGr, clonePolicyGr);
createNewPolicyRecord = false;
}
if (isDraftChild) {
clonePolicyGr.setValue("relationship_state", "2");
clonePolicyGr.setValue("publish_status", "0");
clonePolicyGr.setValue("published_parent", sourcePolicyId);
clonePolicyGr.setValue("order", this.getMaximumOrderOfSiblings(sourcePolicyId) + 100);
var gdt = new GlideDateTime();
var childPolicyName = sourcePolicyGr.name + " " + gdt.getDisplayValue();
clonePolicyGr.setValue("name", childPolicyName);
}
if (!isClonePublish && !isDraftChild) {
clonePolicyGr.setValue("related_policy", sourcePolicyId);
//I don't want check instances to be recreated by business rule
clonePolicyGr.setWorkflow(false);
} else if (isDraftChild) {
// DEF0367389: Prevent BR from creating dupe check instances
clonePolicyGr.setWorkflow(false);
}
if (createNewPolicyRecord) {
if (isClonePublish)
clonePolicyGr.setValue('publish_status', '3'); // Mark queue for reaclc.
var clonePolicyId = clonePolicyGr.insert();
// clone policy was just created, so synchronize the publish status down to the policy state record
this.policyStateUtil.synchronizePolicyStatePublishStatus(clonePolicyGr);
} else {
clonePolicyGr.update();
clonePolicyId = clonePolicyGr.getValue("sys_id");
// clone policy was just updated, so synchronize the publish status down to the policy state record
this.policyStateUtil.synchronizePolicyStatePublishStatus(clonePolicyGr);
}
if (isClonePublish) { //Not relvant for child policy since it allways created in draft mode
sourcePolicyGr.setValue("related_policy", clonePolicyId);
sourcePolicyGr.setWorkflow(false);
sourcePolicyGr.update();
}
//copy all check instances
var sourceCheckGr = new GlideRecord("sn_agent_check");
sourceCheckGr.addQuery("monitoring_policy", sourcePolicyId);
sourceCheckGr.query();
while (sourceCheckGr.next()) {
var cloneCheckGr = this.cloneRecord(sourceCheckGr);
cloneCheckGr.setValue("monitoring_policy", clonePolicyId);
if (!isClonePublish && !isDraftChild) {
cloneCheckGr.setValue("published_check", sourceCheckGr.getValue("sys_id"));
} else if (isDraftChild) {
cloneCheckGr.setValue("published_parent", sourceCheckGr.getValue("sys_id"));
}
cloneCheckGr.setWorkflow(false); // DEF0361960 prevent BR from creating duplicate check instances
var cloneCheckId = cloneCheckGr.insert();
if (isClonePublish) { //Not relvant for child policy since it allways created in draft mode
sourceCheckGr.setValue("published_check", cloneCheckId);
//don't invoke draft busness rules
sourceCheckGr.setWorkflow(false);
sourceCheckGr.update();
}
this.createNewPublishNewCheckParams(sourceCheckGr.getValue("sys_id"), cloneCheckId, isClonePublish, isDraftChild);
this.createNewPublishNewCheckSecureParams(sourceCheckGr.getValue("sys_id"), cloneCheckId, isClonePublish, isDraftChild);
}
return clonePolicyId;
},
getMaximumOrderOfSiblings: function(parentPolicyId) {
var siblingsGr = new GlideAggregate("sn_agent_policy");
siblingsGr.addQuery("published_parent", parentPolicyId);
siblingsGr.groupBy("published_parent");
siblingsGr.addAggregate("MAX", "order");
siblingsGr.query();
if (siblingsGr.next()) {
return parseInt(siblingsGr.getAggregate("MAX", "order"));
}
return 0;
},
cloneRecord: function(sourceRecord, cloneRecord) {
if (!cloneRecord) {
cloneRecord = new GlideRecord(sourceRecord.getTableName());
cloneRecord.initialize();
}
for (var field in cloneRecord) {
if (!field.startsWith("sys")) {
var sourceValue = sourceRecord.getValue(field);
//null doesn't update the record in DB
if (sourceValue == null)
sourceValue = "";
cloneRecord.setValue(field, sourceValue);
}
}
//the copy always switches the draft mode
if (cloneRecord.getValue("is_draft") == 0)
cloneRecord.setValue("is_draft", "1");
else
cloneRecord.setValue("is_draft", "0");
return cloneRecord;
},
republishParentPolicy: function(draftParentPolicyGr, funcName) {
this.createDraftChildIfDoesNotExist(draftParentPolicyGr);
if (funcName == 'republishDraftParentAndChildren')
this.republishDraftParentAndChildren(draftParentPolicyGr);
else
this.publishDraft(draftParentPolicyGr);
},
createDraftChildIfDoesNotExist: function(draftParentPolicyGr) {
var publishedParentPolicyId = draftParentPolicyGr.getValue("related_policy");
var publishedChildPolicyGr = new GlideRecord("sn_agent_policy");
publishedChildPolicyGr.addQuery("published_parent", publishedParentPolicyId);
publishedChildPolicyGr.addQuery("is_draft", "false");
publishedChildPolicyGr.query();
while (publishedChildPolicyGr.next()) {
if (!this.doesPublishedPolicyHasDraftCopy(publishedChildPolicyGr))
this.createDraftFromPublished(publishedChildPolicyGr, false);
}
},
doesPublishedPolicyHasDraftCopy: function(publishedPolicyGr) {
var draftPolicyGr = new GlideRecord("sn_agent_policy");
if (draftPolicyGr.get("related_policy", publishedPolicyGr.getUniqueValue()))
return true;
return false;
},
republishDraftParentAndChildren: function(draftParentPolicyGr) {
// Publish draft parent policy
this.publishDraft(draftParentPolicyGr);
// Publish draft child policies
var publishedParentPolicyId = draftParentPolicyGr.getValue("related_policy");
if (!publishedParentPolicyId)
return;
var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
draftChildPolicyGr.addQuery("published_parent", publishedParentPolicyId);
draftChildPolicyGr.addQuery("is_draft", "true");
draftChildPolicyGr.addQuery("inherit_from_parent", "true");
draftChildPolicyGr.query();
while (draftChildPolicyGr.next())
this.publishDraft(draftChildPolicyGr);
},
markSiblingsAndParentAsQueued: function(parentSysId) {
var publishedKidsGr = new GlideRecord('sn_agent_policy');
publishedKidsGr.addQuery('published_parent', parentSysId);
publishedKidsGr.addActiveQuery();
publishedKidsGr.addQuery('is_draft', '0');
publishedKidsGr.addQuery('inherit_from_parent', '1');
publishedKidsGr.query();
while (publishedKidsGr.next()) {
publishedKidsGr.setValue('publish_status', '3');
publishedKidsGr.update();
// published kid policy just had its publish_status updated, so synchronize it down to the policy state
this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedKidsGr);
}
var parentPolicy = new GlideRecord('sn_agent_policy');
if (!parentPolicy.get('sys_id', parentSysId))
return;
// do not set parent to processing if it is inactive
if (!global.JSUtil.getBooleanValue(parentPolicy, 'active'))
return;
parentPolicy.setValue('publish_status', '3');
parentPolicy.update();
// parent policy just had its publish_status updated, so synchronize it down to the policy state
this.policyStateUtil.synchronizePolicyStatePublishStatus(parentPolicy);
},
publishDraft: function(draftPolicyGr) {
var publishStatus = "1"; // published
if (this.isDraftCriticallyDifferentFromPublished(draftPolicyGr)) {
// If this is a child policy and we need full recalc - publish the entire hierarchy
if (draftPolicyGr.getValue('relationship_state') == '2')
this.markSiblingsAndParentAsQueued(draftPolicyGr.getValue('published_parent'));
// For all other policies
publishStatus = "3"; // Queued = full policy calculation
} else if (this.isDraftDifferentFromPublished(draftPolicyGr))
publishStatus = "5"; // No need to calculate the policy, just publish it to MID servers.
// Create DB view for agent-ci relationship
var view = new AgentPolicyDBView();
if (!view) {
// We will continue to publish despite no view
gs.warn("Could not find AgentPolicyDBView class. Unable to create DB View.");
} else {
view.generateDBView(draftPolicyGr);
}
var draftPolicyId = draftPolicyGr.getValue("sys_id");
//set publish status to "Published"
draftPolicyGr.setValue("publish_status", "1");
//set active value to "Active"
draftPolicyGr.setValue("active", "1");
var publishedPolicyId = draftPolicyGr.getValue("related_policy");
//draft was never published
if (!publishedPolicyId) {
this.clonePolicyTree(draftPolicyGr, true);
} else {
//only update the published status on the draft
draftPolicyGr.update();
// draft policy publish status was updated, so synchronize it down to the policy state record
this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);
var publishedPolicyGr = new GlideRecord("sn_agent_policy");
if (!publishedPolicyGr.get(publishedPolicyId))
return;
this.cloneRecord(draftPolicyGr, publishedPolicyGr);
//clear related policy field
publishedPolicyGr.setValue("related_policy", "");
publishedPolicyGr.setValue("publish_status", publishStatus);
publishedPolicyGr.update();
// published policy publish status was updated, so synchronize it down to all of the policy's policy state records
this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedPolicyGr);
var newPublishedCheckIds = {};
var draftCheckGr = new GlideRecord("sn_agent_check");
draftCheckGr.addQuery("monitoring_policy", draftPolicyId);
draftCheckGr.query();
while (draftCheckGr.next()) {
var publishedCheckId = draftCheckGr.getValue("published_check");
if (publishedCheckId) {
var publishedCheckGr = new GlideRecord("sn_agent_check");
if (!publishedCheckGr.get(publishedCheckId))
continue;
this.cloneRecord(draftCheckGr, publishedCheckGr);
publishedCheckGr.setValue("monitoring_policy", publishedPolicyId);
//clear the published check
publishedCheckGr.setValue("published_check", "");
publishedCheckGr.update();
this.updateExistingPublishedCheckWithCheckParams(draftCheckGr.getValue("sys_id"), publishedCheckId);
this.updateExistingPublishedCheckWithSecureParams(draftCheckGr.getValue("sys_id"), publishedCheckId);
} else {
//check doesn't exist for published record
publishedCheckGr = this.cloneRecord(draftCheckGr);
publishedCheckGr.setValue("monitoring_policy", publishedPolicyId);
publishedCheckId = publishedCheckGr.insert();
//don't invoke draft business rules
draftCheckGr.setWorkflow(false);
draftCheckGr.setValue("published_check", publishedCheckId);
draftCheckGr.update();
//copy all params that belong to current check instance
this.createNewPublishNewCheckParams(draftCheckGr.getValue("sys_id"), publishedCheckId, true);
this.createNewPublishNewCheckSecureParams(draftCheckGr.getValue("sys_id"), publishedCheckId, true);
// If publishedCheckGr is related to a parent policy, it should be copied to all child policies that inherit from it
if (publishedCheckGr.monitoring_policy.relationship_state == "1")
this.copyCheckInstanceToChildPolicies(publishedCheckGr);
}
newPublishedCheckIds[publishedCheckId] = true;
}
//delete all previouse checks that didn't come from last publish
var arrCheckIdsToKeep = Object.keys(newPublishedCheckIds)
publishedCheckGr = new GlideRecord("sn_agent_check");
publishedCheckGr.addQuery("monitoring_policy", publishedPolicyId);
publishedCheckGr.addQuery("sys_id", "NOT IN", Object.keys(newPublishedCheckIds));
publishedCheckGr.deleteMultiple();
if (publishedCheckGr.monitoring_policy.relationship_state == "1")
this.deleteDraftChildPoliciesCheckInstancesBasedOnParentDelete(publishedPolicyId, arrCheckIdsToKeep);
}
},
deleteDraftChildPoliciesCheckInstancesBasedOnParentDelete: function(publishedParentSysId, arrParentCheckIdsToKeep) {
if (!arrParentCheckIdsToKeep || arrParentCheckIdsToKeep.length < 1)
return;
var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
draftChildPolicyGr.addQuery("published_parent", publishedParentSysId);
draftChildPolicyGr.addQuery("is_draft", "true");
draftChildPolicyGr.addQuery("inherit_from_parent", "true");
draftChildPolicyGr.query();
while (draftChildPolicyGr.next()) {
cloneCheckGr = new GlideRecord('sn_agent_check');
cloneCheckGr.addQuery("monitoring_policy", draftChildPolicyGr.getUniqueValue());
cloneCheckGr.addQuery("published_parent", "NOT IN", arrParentCheckIdsToKeep);
cloneCheckGr.deleteMultiple();
}
},
copyCheckInstanceToChildPolicies: function(publishedParentCheckInstanceGr) {
var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
draftChildPolicyGr.addQuery("published_parent", publishedParentCheckInstanceGr.getValue("monitoring_policy"));
draftChildPolicyGr.addQuery("is_draft", "true");
draftChildPolicyGr.addQuery("inherit_from_parent", "true");
draftChildPolicyGr.query();
while (draftChildPolicyGr.next()) {
this.copyCurrentCheckInstanceToChildPolicy(draftChildPolicyGr.getUniqueValue(), publishedParentCheckInstanceGr);
this.updateChildPolicyChecksStr(draftChildPolicyGr, publishedParentCheckInstanceGr);
this.updatePublishStatusToEditedChildPolicy(draftChildPolicyGr);
draftChildPolicyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(draftChildPolicyGr);
}
},
copyCurrentCheckInstanceToChildPolicy: function(childePolicyId, publishedParentCheckGr) {
var publishedParentCheckId = publishedParentCheckGr.getUniqueValue();
var cloneCheckGr = undefined;
cloneCheckGr = new GlideRecord('sn_agent_check');
cloneCheckGr.addQuery("monitoring_policy", childePolicyId);
cloneCheckGr.addQuery("published_parent", publishedParentCheckId);
cloneCheckGr.query();
if (!cloneCheckGr.next())
cloneCheckGr = this.cloneRecord(publishedParentCheckGr);
else
this.cloneRecord(publishedParentCheckGr, cloneCheckGr);
// A business rule prevents us form inserting a new check: we want to keep the business rule and insert here
cloneCheckGr.setWorkflow(false);
cloneCheckGr.setValue("monitoring_policy", childePolicyId);
cloneCheckGr.setValue("published_parent", publishedParentCheckId);
cloneCheckGr.update();
var cloneCheckId = cloneCheckGr.getUniqueValue();
this.copyCheckParams(cloneCheckId, publishedParentCheckId, "sn_agent_check_param");
this.copyCheckParams(cloneCheckId, publishedParentCheckId, "sn_agent_check_secure_param");
},
copyCheckParams: function(cloneCheckId, publishedParentCheckId, checkParamsTable) {
var publishedCheckParamGr = new GlideRecord(checkParamsTable);
publishedCheckParamGr.addQuery("check", publishedParentCheckId);
publishedCheckParamGr.addQuery("is_draft", false);
publishedCheckParamGr.query();
while (publishedCheckParamGr.next()) {
var cloneCheckParamGr = undefined;
cloneCheckParamGr = new GlideRecord(checkParamsTable);
cloneCheckParamGr.addQuery("check", cloneCheckId);
cloneCheckParamGr.addQuery("published_parent", publishedCheckParamGr.getUniqueValue());
cloneCheckParamGr.query();
if (!cloneCheckParamGr.next())
cloneCheckParamGr = this.cloneRecord(publishedCheckParamGr);
else
this.cloneRecord(publishedCheckParamGr, cloneCheckParamGr);
cloneCheckParamGr.setWorkflow(false);
cloneCheckParamGr.setValue("check", cloneCheckId);
cloneCheckParamGr.setValue("published_parent", publishedCheckParamGr.getUniqueValue());
cloneCheckParamGr.update();
}
},
updateChildPolicyChecksStr: function(draftChildPolicyGr, publishedParentCheckInstanceGr) {
var updatedChecksStr = draftChildPolicyGr.getValue("checks_str") + "," + publishedParentCheckInstanceGr.getValue("check_def");
draftChildPolicyGr.setValue("checks_str", updatedChecksStr);
},
updatePublishStatusToEditedChildPolicy: function(draftChildPolicyGr) {
// If the child's publish_status field is 'Published', change it to 'Published*'
if (draftChildPolicyGr.getValue("publish_status") == "1") {
this.updatePublishedChildPolicyStatus(draftChildPolicyGr.getValue("related_policy"), "2");
draftChildPolicyGr.setValue("publish_status", "2");
}
},
updatePublishedChildPolicyStatus: function(publishedChildPolicyId, statusValue) {
var policyGr = new GlideRecord("sn_agent_policy");
if (policyGr.get(publishedChildPolicyId)) {
policyGr.setValue("publish_status", statusValue);
policyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(policyGr);
}
},
createDraftFromPublished: function(publishedRecord, isDraftChild) {
var currentDomain = new sn_agent.DomainInfo().getCurrentDomain();
var publishedRecordDomain = publishedRecord.getValue("sys_domain");
if (currentDomain != publishedRecordDomain) {
publishedRecord = this.copyPolicyTreeToCurrentDomain(publishedRecord);
}
var isDraftShouldBeOverride = false;
var parentDomainDraftSysID = "";
if (publishedRecord.sys_overrides) {
parentDomainDraftSysID = this.getParentDomainDraftSysID(publishedRecord.sys_overrides);
if (parentDomainDraftSysID != "")
isDraftShouldBeOverride = true;
}
var clonePolicyId = this.clonePolicyTree(publishedRecord, false, null, isDraftChild);
if (isDraftShouldBeOverride && !isDraftChild) {
this.setOverrideForDraft(clonePolicyId, parentDomainDraftSysID);
}
return clonePolicyId;
},
createDraftChildFromPublished: function(publishedPolicy) {
var publishedParentPolicyInCurrentDomain = publishedPolicy;
var childPolicyID = this.createDraftFromPublished(publishedPolicy, true);
var currentDomain = new sn_agent.DomainInfo().getCurrentDomain();
var publishedPolicyDomain = publishedPolicy.getValue("sys_domain");
if (currentDomain != publishedPolicyDomain) {
// publishedPolicy has already been copied to the current domain in the createDraftFromPublished() function
publishedParentPolicyInCurrentDomain = this.getRecordInCurrentDomain(publishedPolicy.getValue("sys_id"), "sn_agent_policy");
}
this.updateRelationshipStateToPublishAndDraftParent(publishedParentPolicyInCurrentDomain);
return childPolicyID;
},
getRecordInCurrentDomain: function(recordId, table) {
var gr = new GlideRecord(table);
if (gr.get("sys_overrides", recordId))
return gr;
return null;
},
updateRelationshipStateToPublishAndDraftParent: function(publishedPolicy) {
publishedPolicy.setValue("relationship_state", "1");
publishedPolicy.update();
var draftPolicyGR = this.getRelatedPolicy(publishedPolicy.sys_id);
if (draftPolicyGR != null) {
draftPolicyGR.setValue("relationship_state", "1");
draftPolicyGR.setWorkflow(false);
draftPolicyGR.update();
}
},
createDraft: function(publishedPolicy) {
var clonePolicyId = this.createDraftFromPublished(publishedPolicy, false);
if (!publishedPolicy.relationship_state) { //OOB need to fix that field
publishedPolicy.setValue("relationship_state", "0");
publishedPolicy.setWorkflow(false);
publishedPolicy.update();
}
return clonePolicyId;
},
getParentDomainDraftSysID: function(sourceParentDomainSysID) {
var policyPublishedForParentDomain = new GlideRecord("sn_agent_policy");
policyPublishedForParentDomain.addQuery("related_policy", sourceParentDomainSysID);
policyPublishedForParentDomain.query();
if (policyPublishedForParentDomain.next()) {
return policyPublishedForParentDomain.sys_id;
}
return "";
},
setOverrideForDraft: function(clonePolicyId, parentDomainDraftSysID) {
var cloneDraftCurrentDomain = new GlideRecord("sn_agent_policy");
var found = cloneDraftCurrentDomain.get(clonePolicyId);
if (found) {
cloneDraftCurrentDomain.sys_overrides = parentDomainDraftSysID;
cloneDraftCurrentDomain.update();
}
},
copyPolicyTreeToCurrentDomain: function(sourcePolicyOldDomainGr) {
var sourcePolicyNewDomainGr;
// If there is a policy hierarchy of parent policy and child policies, copy the entire tree
var parentPolicySysId = sourcePolicyOldDomainGr.getValue("sys_id");
if (sourcePolicyOldDomainGr.getValue("relationship_state") == "2") {
// sourcePolicyOldDomainGr is a child policy
parentPolicySysId = sourcePolicyOldDomainGr.getValue("published_parent");
}
var policyGr = new GlideRecord("sn_agent_policy");
var qc1 = policyGr.addQuery("is_draft", false);
qc1.addOrCondition("publish_status", "0");
var qc2 = policyGr.addQuery("published_parent", parentPolicySysId);
qc2.addOrCondition("sys_id", parentPolicySysId);
policyGr.orderBy("published_parent"); // The orderBy("published_parent") ensures that we copy the parent policy first and then the child policies
policyGr.query();
while (policyGr.next()) {
var currentIsTheSourcePolicy = sourcePolicyOldDomainGr.getValue("sys_id") == policyGr.getValue("sys_id");
var currentPolicyNewDomainGr = this.copyPolicyEntitiesToCurrentDomain(policyGr);
if (policyGr.getValue("relationship_state") == "1") {
// policyGr is a parent policy, save the parent policy sys_id in the current domain
parentPolicySysId = currentPolicyNewDomainGr.getValue("sys_id");
}
if (policyGr.getValue("relationship_state") == "2") {
// policyGr is a child policy, update its parent policy in the current domain
currentPolicyNewDomainGr.setValue("published_parent", parentPolicySysId);
currentPolicyNewDomainGr.update();
}
if (currentIsTheSourcePolicy) {
sourcePolicyNewDomainGr = currentPolicyNewDomainGr;
}
}
return sourcePolicyNewDomainGr;
},
copyPolicyEntitiesToCurrentDomain: function(sourcePolicyOldDomainGr) {
var oldDomainPolicyID = sourcePolicyOldDomainGr.getValue("sys_id");
sourcePolicyOldDomainGr.setWorkflow(false);
sourcePolicyOldDomainGr.update();
var newDomainPolicyID = sourcePolicyOldDomainGr.getValue("sys_id");
this.copyChecksTreeToCurrentDomain(oldDomainPolicyID, newDomainPolicyID);
var sourcePolicyNewDomainGr = new GlideRecord("sn_agent_policy");
sourcePolicyNewDomainGr.get(newDomainPolicyID);
return sourcePolicyNewDomainGr;
},
copyChecksTreeToCurrentDomain: function(oldDomainPolicyID, newDomainPolicyID) {
//copy all check instances from domain father to domain child
var sourceCheckOldDomainGr = new GlideRecord("sn_agent_check");
sourceCheckOldDomainGr.addQuery("monitoring_policy", oldDomainPolicyID);
sourceCheckOldDomainGr.query();
var newDomainCheckID, oldDomainCheckID;
while (sourceCheckOldDomainGr.next()) {
oldDomainCheckID = sourceCheckOldDomainGr.getValue("sys_id");
sourceCheckOldDomainGr.setWorkflow(false);
sourceCheckOldDomainGr.setValue("monitoring_policy", newDomainPolicyID);
if (sourceCheckOldDomainGr.getValue("published_parent")) {
var checkPublishedParentGr = this.getRecordInCurrentDomain(sourceCheckOldDomainGr.getValue("published_parent"), "sn_agent_check");
sourceCheckOldDomainGr.setValue("published_parent", checkPublishedParentGr.getUniqueValue());
}
sourceCheckOldDomainGr.update();
newDomainCheckID = sourceCheckOldDomainGr.getValue("sys_id");
this.copyAllCheckParamsInstanceToCurrentDomain(oldDomainCheckID, newDomainCheckID);
}
},
copyAllCheckParamsInstanceToCurrentDomain: function(oldDomainCheckID, newDomainCheckID) {
this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_param", "check");
this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_secure_param", "check");
},
copyAllCheckParamsDefToCurrentDomain: function(oldDomainCheckID, newDomainCheckID) {
this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_param_def", "check_def");
this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_secure_param_def", "check_def");
},
copyCheckParamsToCurrentDomain: function(oldDomainCheckID, newDomainCheckID, paramTableName, checkRefField) {
//copy all check params from domain father to domain child
var sourceParamsOldDomainGr = new GlideRecord(paramTableName);
sourceParamsOldDomainGr.addQuery(checkRefField, oldDomainCheckID);
sourceParamsOldDomainGr.query();
while (sourceParamsOldDomainGr.next()) {
sourceParamsOldDomainGr.setWorkflow(false);
sourceParamsOldDomainGr.setValue(checkRefField, newDomainCheckID);
if (sourceParamsOldDomainGr.getValue("published_parent")) {
var checkParamPublishedParentGr = this.getRecordInCurrentDomain(sourceParamsOldDomainGr.getValue("published_parent"), paramTableName);
sourceParamsOldDomainGr.setValue("published_parent", checkParamPublishedParentGr.getUniqueValue());
}
sourceParamsOldDomainGr.update();
}
},
revertDraft: function(policyDraftId) {
var draftPolicyGr = new GlideRecord("sn_agent_policy");
if (!draftPolicyGr.get(policyDraftId))
return;
var publishedPolicyId = draftPolicyGr.getValue("related_policy");
var publishedPolicyGr = new GlideRecord("sn_agent_policy");
if (!publishedPolicyGr.get(publishedPolicyId))
return;
//make sure to revert the status to published if needed
if (publishedPolicyGr.getValue("publish_status") != "1") {
publishedPolicyGr.setValue("publish_status", "1");
//status shouldn't change the timestamp of the policy
publishedPolicyGr.setWorkflow(false);
publishedPolicyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedPolicyGr);
}
var draftPolicyId = draftPolicyGr.getValue("sys_id");
var draftCheckGr = new GlideRecord("sn_agent_check");
draftCheckGr.addQuery("monitoring_policy", draftPolicyId);
draftCheckGr.query();
draftCheckGr.setWorkflow(false);
draftCheckGr.deleteMultiple();
//recopy everything from published to draft
this.clonePolicyTree(publishedPolicyGr, false, draftPolicyGr);
},
updatePublishStatusOnDraftCheckChange: function(draftCheckGr) {
var draftRelatedPolicyGr = new GlideRecord("sn_agent_policy");
var draftPolicyId = draftCheckGr.getValue("monitoring_policy");
if (!draftRelatedPolicyGr.get(draftPolicyId))
return;
if (draftRelatedPolicyGr.getValue("publish_status") == "1") {
draftRelatedPolicyGr.setValue("publish_status", "2");
draftRelatedPolicyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(draftRelatedPolicyGr);
var publishedRelatedPolicyGr = new GlideRecord("sn_agent_policy");
if (!publishedRelatedPolicyGr.get(draftRelatedPolicyGr.getValue("related_policy")))
return;
publishedRelatedPolicyGr.setValue("publish_status", "2");
publishedRelatedPolicyGr.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedRelatedPolicyGr);
}
},
updatePublishStatusOnDraftParamChange: function(draftParamGr) {
var draftCheckGr = new GlideRecord("sn_agent_check");
if (!draftCheckGr.get(draftParamGr.getValue("check")))
return;
this.updatePublishStatusOnDraftCheckChange(draftCheckGr);
},
fixAllPreviousDataToPublished: function() {
var policyGr = new GlideRecord("sn_agent_policy");
policyGr.addEncodedQuery("publish_statusIN1,2");
policyGr.query();
//run fix script only in case we are in case we are in env that wasn't working with draft mode.
if (!policyGr.next()) {
gs.info("setting is_draft to false for all existing data");
var paramGr = new GlideRecord("sn_agent_check_param");
paramGr.setValue("is_draft", false);
paramGr.setWorkflow(false);
paramGr.updateMultiple();
var checkGr = new GlideRecord("sn_agent_check");
checkGr.setValue("is_draft", false);
checkGr.setWorkflow(false);
checkGr.updateMultiple();
policyGr = new GlideRecord("sn_agent_policy");
policyGr.setValue("is_draft", false);
policyGr.setValue("publish_status", "1");
policyGr.setWorkflow(false);
policyGr.updateMultiple();
} else {
gs.info("env already has published policies, the fix script shouldn't run");
}
},
getCheckInstanceDraftId: function(publishedCheckGr) {
var checkInstanceGr = new GlideRecord("sn_agent_check");
checkInstanceGr.addQuery("published_check", publishedCheckGr.sys_id);
checkInstanceGr.query();
if (checkInstanceGr.next()) {
return checkInstanceGr.getValue("sys_id");
} else {
//this version came from upgrade and doesn't have draft
var publishedPolicyGr = new GlideRecord("sn_agent_policy");
var policyId = publishedCheckGr.getValue("monitoring_policy");
if (publishedPolicyGr.get(policyId)) {
this.createDraft(publishedPolicyGr);
// in case the draft was created in a different domain, let's find the correct pusblished check
checkInstanceGr = new GlideRecord("sn_agent_check");
checkInstanceGr.addQuery("sys_domain", new DomainInfo().getCurrentDomain());
checkInstanceGr.addQuery("sys_overrides", publishedCheckGr.getUniqueValue());
checkInstanceGr.query();
if (checkInstanceGr.next())
publishedCheckGr = checkInstanceGr;
//now query again...
checkInstanceGr = new GlideRecord("sn_agent_check");
checkInstanceGr.addQuery("published_check", publishedCheckGr.sys_id);
checkInstanceGr.query();
if (checkInstanceGr.next()) {
return checkInstanceGr.getValue("sys_id");
}
}
}
},
updateExistingPublishedCheckWithCheckParams: function(draftCheckId, publishedCheckId) {
this.updateExistingPublishedCheckparams(draftCheckId, publishedCheckId, "sn_agent_check_param", "published_param");
},
updateExistingPublishedCheckWithSecureParams: function(draftCheckId, publishedCheckId) {
this.updateExistingPublishedCheckparams(draftCheckId, publishedCheckId, "sn_agent_check_secure_param", "published_secure_param");
},
createNewPublishNewCheckParams: function(draftCheckId, publishedCheckId, isPublish, isChild) {
this.createNewPublishCheckParams(draftCheckId, publishedCheckId, "sn_agent_check_param", "published_param", isPublish, isChild);
},
createNewPublishNewCheckSecureParams: function(draftCheckId, publishedCheckId, isPublish, isChild) {
this.createNewPublishCheckParams(draftCheckId, publishedCheckId, "sn_agent_check_secure_param", "published_secure_param", isPublish, isChild);
},
updateExistingPublishedCheckparams: function(draftCheckId, publishedCheckId, paramTable, referenceField) {
var newPublishedParamIds = {};
//copy all check params that belong to current check instance
var draftParamsGr = new GlideRecord(paramTable);
draftParamsGr.addQuery("check", draftCheckId);
draftParamsGr.query();
while (draftParamsGr.next()) {
var publishedParamId = draftParamsGr.getValue(referenceField);
if (publishedParamId) {
var publishedParamGr = new GlideRecord(paramTable);
if (!publishedParamGr.get(publishedParamId))
continue;
this.cloneRecord(draftParamsGr, publishedParamGr);
publishedParamGr.setValue("check", publishedCheckId);
//clear the published check param field that was copied from draft
publishedParamGr.setValue(referenceField, "");
publishedParamGr.update();
} else {
//check param doesn't exist in published records
publishedParamGr = this.cloneRecord(draftParamsGr);
publishedParamGr.setValue("check", publishedCheckId);
publishedParamId = publishedParamGr.insert();
//don't invoke draft business rules, for the published param
draftParamsGr.setValue(referenceField, publishedParamId);
draftParamsGr.setWorkflow(false);
draftParamsGr.update();
}
newPublishedParamIds[publishedParamId] = true;
}
//delete all previouse check params that didn't come from last publish
var publishedParamsGr = new GlideRecord(paramTable);
publishedParamsGr.addQuery("check", publishedCheckId);
publishedParamsGr.addQuery("sys_id", "NOT IN", Object.keys(newPublishedParamIds));
publishedParamsGr.deleteMultiple();
},
createNewPublishCheckParams: function(draftCheckId, publishedCheckId, paramTable, referenceField, isPublish, isChild) {
//copy all check params that belong to current check instance
var draftParamsGr = new GlideRecord(paramTable);
draftParamsGr.addQuery("check", draftCheckId);
draftParamsGr.query();
while (draftParamsGr.next()) {
var publishedParamGr = this.cloneRecord(draftParamsGr);
publishedParamGr.setValue("check", publishedCheckId);
if (!isPublish && !isChild) {
publishedParamGr.setValue(referenceField, draftParamsGr.getValue("sys_id"));
} else if (isChild) {
publishedParamGr.setValue("published_parent", draftParamsGr.getValue("sys_id"));
}
publishedParamGr.setWorkflow(false);
var publishedParamId = publishedParamGr.insert();
// we are interested only in notification about check params table
if (paramTable == "sn_agent_check_param") {
gs.eventQueue("sn_agent.notify_check_param_creation", publishedParamGr); //send event to notify about param creation, listener exists in acc_l
}
//Not relevant for child policy since it always created in draft mode
if (isPublish) {
//don't invoke draft business rules
draftParamsGr.setWorkflow(false);
draftParamsGr.setValue(referenceField, publishedParamId);
draftParamsGr.update();
}
}
},
getSandboxPolicyId: function(publishedPolicyGR) {
var currentDomain = new DomainInfo().getCurrentDomain();
var draftPolicyGr = new GlideRecord("sn_agent_policy");
draftPolicyGr.addQuery("related_policy", publishedPolicyGR.sys_id);
draftPolicyGr.addQuery("sys_domain", currentDomain);
draftPolicyGr.query();
if (draftPolicyGr.next()) {
var draftSysId = draftPolicyGr.sys_id;
} else {
draftSysId = this.createDraft(publishedPolicyGR);
}
return draftSysId;
},
changeActiveValueForPolicy: function(current, activeValue) {
var currentDomain = new DomainInfo().getCurrentDomain();
var publishedRecordDoamin = current.sys_domain;
if (currentDomain != publishedRecordDoamin) {
current = this.copyPolicyTreeToCurrentDomain(current);
}
// Only if we change to active value on the db level
if (activeValue && current.active != activeValue) {
var p = new PolicyClientsGeneratorNG();
var policyFullCalcCycleTime = p.getPolicyFullCalcCycleAsGlideTime();
var policyStateGr = new GlideRecord('sn_agent_policy_state');
policyStateGr.addQuery('policy', current.getUniqueValue());
policyStateGr.query();
while (policyStateGr.next()) {
var lastCalcTime = new GlideDateTime(policyStateGr.getValue('last_full_calc_time'));
var domainId = policyStateGr.getValue('sys_domain');
// If it has been more than the full re-calc cycle, once the policy activated we will do a full calc - so it will be a no-op here.
// But if it was not: turn the flag to run CMDB changes on the policy that will run CMDB changes and publishing within a minute.
if (!policyFullCalcCycleTime.after(lastCalcTime))
p.getAndUpdateReCalcFilterFlag("true", domainId);
}
current.publish_status = "4"; // Indicate processing
}
current.active = activeValue;
current.update();
this.policyStateUtil.synchronizePolicyStatePublishStatus(current);
// Create DB view for activated policy
var view = new AgentPolicyDBView();
if (activeValue) {
if (view)
view.generateDBView(current);
}
},
/*
This method returns true if there was a critical change in the policy.
A critical change in the policy would trigger a full policy calculation.
Critical change is define whether how we get the monitored CIs changed, if we change the proxy agents settings - cannot compare checks.
*/
arePoliciesCriticallyDifferent: function(policyGr1, policyGr2) {
if (policyGr1.getValue("relationship_state") == '2' &&
policyGr1.getValue("order") != policyGr2.getValue("order"))
return true;
for (var field in this.CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD) {
var booleanValueToCheck = this.CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD[field];
// If we have a boolean value to check first, make sure it is set to true.
if (booleanValueToCheck) {
if (policyGr1.getValue(booleanValueToCheck) != 1)
continue;
}
if (policyGr1.getValue(field) != policyGr2.getValue(field))
return true;
}
return false;
},
isDraftCriticallyDifferentFromPublished: function(draftGr) {
if (!draftGr || !draftGr.sys_id || !draftGr.is_draft)
return false;
var publishPolicySysId = draftGr.getValue('related_policy');
if (!publishPolicySysId)
return true;
var publishGr = new GlideRecord('sn_agent_policy');
if (!publishGr.get('sys_id', publishPolicySysId))
return true;
var diff = this.arePoliciesCriticallyDifferent(draftGr, publishGr);
if (diff)
return true;
// Continue to compare checks.
var p = new PolicyClientsGeneratorNG();
var numOfChecksOnPublished = p.rapidRowCount('sn_agent_check', 'monitoring_policy=' + publishPolicySysId + '^active=true');
var numOfChecksOnDraft = p.rapidRowCount('sn_agent_check', 'monitoring_policy=' + draftGr.getValue('sys_id') + '^active=true');
if (numOfChecksOnPublished != numOfChecksOnDraft)
return true;
var draftChecksGr = new GlideRecord('sn_agent_check');
draftChecksGr.addQuery('monitoring_policy', draftGr.getValue('sys_id'));
draftChecksGr.addActiveQuery();
draftChecksGr.query();
while (draftChecksGr.next()) {
var publishedCheckSysId = draftChecksGr.getValue('published_check');
if (!publishedCheckSysId)
return true;
var publishCheck = new GlideRecord('sn_agent_check');
if (!publishCheck.get('sys_id', publishedCheckSysId))
return true;
if (draftChecksGr.getValue('active') != publishCheck.getValue('active') ||
draftChecksGr.getValue('check_def') != publishCheck.getValue('check_def'))
return true;
// If auto generated, check if the number of CI params is different
if (draftChecksGr.getValue('auto_generate') == '1') {
var ciParamRegEx = '{{.labels.params_ci_';
var draftCiParams = [];
var publishCiParams = [];
// Get all ci params keys using regex
var myRegexp = new RegExp(ciParamRegEx + "(.*?)}}", "gm");
var match = myRegexp.exec(draftChecksGr.getValue('command'));
while (match != null) {
if (match[1]) {
draftCiParams.push(match[1]);
}
match = myRegexp.exec(draftChecksGr.getValue('command'));
}
match = myRegexp.exec(publishCheck.getValue('command'));
while (match != null) {
if (match[1]) {
publishCiParams.push(match[1]);
}
match = myRegexp.exec(publishCheck.getValue('command'));
}
if (publishCiParams.length != draftCiParams.length)
return true;
// Items in both arrays can be identical but not in order.
// As the result is the same regardless of order, we will sort the arrays to make sure the content is different and not the order.
publishCiParams.sort();
draftCiParams.sort();
for (var i = 0; i < publishCiParams.length; i++)
if (publishCiParams[i] != draftCiParams[i])
return true;
}
}
return false;
},
isDraftDifferentFromPublished: function(draftGr) {
if (!draftGr || !draftGr.sys_id || !draftGr.is_draft)
return false;
if (this.isDraftCriticallyDifferentFromPublished(draftGr))
return true;
var publishPolicySysId = draftGr.getValue('related_policy');
if (!publishPolicySysId)
return true;
var publishGr = new GlideRecord('sn_agent_policy');
if (!publishGr.get('sys_id', publishPolicySysId))
return false;
var excludedComparisonFields = this.POLICY_EXCLUDED_COMPARISON_FIELDS;
var checkExcludedComparisonFields = this.CHECK_EXCLUDED_COMPARISON_FIELDS;
var paramsExcludedComparisonFields = this.PARAMS_EXCLUDED_COMPARISON_FIELDS;
var isEqual = this.areRecordsFieldsEqual(draftGr, publishGr, excludedComparisonFields);
if (!isEqual)
return true;
// Continue to compare checks.
var draftChecksGr = new GlideRecord('sn_agent_check');
draftChecksGr.addQuery('monitoring_policy', draftGr.getValue('sys_id'));
draftChecksGr.query();
var checkFields = draftChecksGr.getElements();
var paramsFields = undefined;
var secureParamsFields = undefined;
while (draftChecksGr.next()) {
var publishedCheckSysId = draftChecksGr.getValue('published_check');
if (!publishedCheckSysId)
return true;
var publishCheck = new GlideRecord('sn_agent_check');
if (!publishCheck.get('sys_id', publishedCheckSysId))
return true;
isEqual = this.areRecordsFieldsEqual(draftChecksGr, publishCheck, checkExcludedComparisonFields, checkFields);
if (!isEqual)
return true;
// Now compare the check's parameters.
var draftCheckparam = new GlideRecord('sn_agent_check_param');
draftCheckparam.addQuery('check', draftChecksGr.getUniqueValue());
draftCheckparam.query();
if (!paramsFields)
paramsFields = draftCheckparam.getElements();
while (draftCheckparam.next()) {
var publishedCheckParamSysId = draftCheckparam.getValue('published_param');
if (!publishedCheckParamSysId)
return true;
var publishedCheckparam = new GlideRecord('sn_agent_check_param');
if (!publishedCheckparam.get('sys_id', publishedCheckParamSysId))
return true;
isEqual = this.areRecordsFieldsEqual(draftCheckparam, publishedCheckparam, paramsExcludedComparisonFields, paramsFields);
if (!isEqual)
return true;
}
// now compare the check's secure parameters.
draftCheckparam = new GlideRecord('sn_agent_check_secure_param');
draftCheckparam.addQuery('check', draftChecksGr.getUniqueValue());
draftCheckparam.query();
if (!secureParamsFields)
secureParamsFields = draftCheckparam.getElements();
while (draftCheckparam.next()) {
var publishedCheckParamSysId = draftCheckparam.getValue('published_secure_param');
if (!publishedCheckParamSysId)
return true;
var publishedCheckparam = new GlideRecord('sn_agent_check_secure_param');
if (!publishedCheckparam.get('sys_id', publishedCheckParamSysId))
return true;
isEqual = this.areRecordsFieldsEqual(draftCheckparam, publishedCheckparam, paramsExcludedComparisonFields, secureParamsFields);
if (!isEqual)
return true;
}
}
return false;
},
/**
This method compares 2 records on 2 GlideRecord pointing to the same table.
The method does this by comparing a value of a field from gr1 with the value of the same field in gr2.
The method skips the system fields as they are expected to be different.
The method support an exlusion list which will instruct the method to not compare specific fields.
The method support an input on fields to be compared, otherwise the method will comapre all table's fields.
@params:
gr1 - a GlideRecord that points to a specific record on a table
gr2 - a GlideRecord that points to a specific record on the same table as gr1
exclusionList - an array of field names to exclue (skip) in the comparison
fields - OPTIONAL. Get the fields to comapre between gr1 and gr2.
@return
true if every field's value from gr1 is equale to the same field's value in gr2, otherwise false.
*/
areRecordsFieldsEqual: function(gr1, gr2, exclusionList, fields) {
if (gr1.getTableName() != gr2.getTableName())
return false;
if (!fields)
fields = gr1.getElements();
for (var i = 0; i < fields.length; i++) {
var fieldName = fields[i].getName();
// Skip system fields and excluded fields
if (exclusionList.indexOf(fieldName) > -1 || fieldName.startsWith('sys_'))
continue;
if (gr1.getValue(fieldName) != gr2.getValue(fieldName))
return false;
}
return true;
},
type: 'PolicyDraftUtils'
};
Sys ID
5b945a5a67064410b7b72dbd2685ef9c