Skip to content

Commit

Permalink
Merge pull request #26 from splunk/fix/new-features-from-sc4snmp
Browse files Browse the repository at this point in the history
Fix/new features from sc4snmp
  • Loading branch information
wojtekzyla committed Jul 7, 2023
2 parents 6604c8f + 3f7bbdf commit 564830a
Show file tree
Hide file tree
Showing 17 changed files with 923 additions and 550 deletions.
93 changes: 78 additions & 15 deletions backend/SC4SNMP_UI_backend/common/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,31 @@ def ui2backend(self, document: dict, **kwargs):
class ProfileConversion(Conversion):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__backend2ui_conditional_operations = {
"lt": "less than",
"gt": "greater than",
"equal": "equal",
"in": "in"
}
self.__ui2backend_conditional_operations = {}
for key, value in self.__backend2ui_conditional_operations.items():
self.__ui2backend_conditional_operations[value] = key

self.__backend2ui_profile_types = {
"field": "smart"
}
self.__ui2backend_profile_types = {}
for key, value in self.__backend2ui_profile_types.items():
self.__ui2backend_profile_types[value] = key

def __string_value_to_numeric(self, value: str):
try:
if value.isnumeric():
return int(value)
elif value.replace(".", "").isnumeric():
return float(value)
except ValueError:
return value

def _backend2ui_map(self, document: dict, **kwargs):
profile_name = None
Expand All @@ -61,26 +86,48 @@ def _backend2ui_map(self, document: dict, **kwargs):
new_vb = {
"family": vb[0],
"category": vb[1] if len(vb) >= 2 else "",
"index": str(vb[2]) if len(vb) == 3 else "",
"index": '.'.join(vb[2:]) if len(vb) >= 3 else "",
}
var_binds.append(new_vb)

if "condition" in document[profile_name]:
backend_condition = document[profile_name]["condition"]
condition_type = backend_condition["type"]
field = backend_condition["field"] if condition_type == "field" else ""
condition_type = self.__backend2ui_profile_types[backend_condition["type"]]
field = backend_condition["field"] if backend_condition["type"] == "field" else ""
patterns = [{"pattern": p} for p in backend_condition["patterns"]] \
if condition_type == "field" else None
if backend_condition["type"] == "field" else []
conditions = {
"condition": condition_type,
"field": field,
"patterns": patterns
"patterns": patterns,
"conditions": []
}
elif "conditions" in document[profile_name]:
conditional = []
for back_condition in document[profile_name]["conditions"]:
field = back_condition["field"]
operation = self.__backend2ui_conditional_operations[back_condition["operation"]]
value = []
if operation == "in":
for v in back_condition["value"]:
value.append(str(v))
else:
value.append(str(back_condition["value"]))
conditional.append(
{"field": field, "operation": operation, "value": value}
)
conditions = {
"condition": "conditional",
"field": "",
"patterns": [],
"conditions": conditional
}
else:
conditions = {
"condition": "None",
"condition": "standard",
"field": "",
"patterns": None
"patterns": [],
"conditions": []
}
result = {
"_id": str(document["_id"]),
Expand All @@ -92,16 +139,30 @@ def _backend2ui_map(self, document: dict, **kwargs):
return result

def _ui2backend_map(self, document: dict, **kwargs):
if document['conditions']['condition'] == "field":
conditions = {
conditions = None
condition = None
if document['conditions']['condition'] == "smart":
condition = {
'type': 'field',
'field': document['conditions']['field'],
'patterns': [el['pattern'] for el in document['conditions']['patterns']]
}
elif document['conditions']['condition'] == "None":
conditions = None
else:
conditions = {
elif document['conditions']['condition'] == "conditional":
conditions = []
for ui_condition in document['conditions']['conditions']:
field = ui_condition["field"]
operation = self.__ui2backend_conditional_operations[ui_condition["operation"]]
if operation == "in":
value = []
for v in ui_condition["value"]:
value.append(self.__string_value_to_numeric(v))
else:
value = self.__string_value_to_numeric(ui_condition["value"][0])
conditions.append(
{"field": field, "operation": operation, "value": value}
)
elif document['conditions']['condition'] != "standard":
condition = {
'type': document['conditions']['condition']
}
var_binds = []
Expand All @@ -110,7 +171,7 @@ def _ui2backend_map(self, document: dict, **kwargs):
if len(var_b['category']) > 0:
single_var_bind.append(var_b['category'])
if len(var_b['index']) > 0:
single_var_bind.append(int(var_b['index']))
single_var_bind += var_b['index'].split(".")
var_binds.append(single_var_bind)

item = {
Expand All @@ -119,8 +180,10 @@ def _ui2backend_map(self, document: dict, **kwargs):
'varBinds': var_binds
}
}
if condition is not None:
item[document['profileName']].update({'condition': condition})
if conditions is not None:
item[document['profileName']].update({'condition': conditions})
item[document['profileName']].update({'conditions': conditions})
return item


Expand Down
4 changes: 2 additions & 2 deletions backend/SC4SNMP_UI_backend/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ def add_group_to_inventory(self, group_name: str, group_port: str, group_object=
deleted_inventory_record = list(self._mongo_inventory.find({'address': group_name, "delete": True}))
group = list(self._mongo_groups.find({group_name: {"$exists": 1}}))
if len(group) == 0:
group_added = False
message = f"There is no group {group_name} configured. Record was not added."
group_added = True
message = f"Group {group_name} doesn't exist in the configuration. Treating {group_name} as a hostname."
elif len(existing_inventory_record) > 0:
group_added = False
message = f"Group {group_name} has already been added to the inventory. Record was not added."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ function Header(){
const handleRequestOpenProfile = () => {
ProfCtx.setProfileName("");
ProfCtx.setFrequency(1);
ProfCtx.setVarBinds(null);
ProfCtx.setConditions(null);
ProfCtx.setVarBinds([]);
ProfCtx.setCondition("None");
ProfCtx.setConditionField("");
ProfCtx.setConditionPatterns([]);
ProfCtx.setConditional([]);
ProfCtx.setAddOpen(true);
ProfCtx.setIsEdit(false);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import Number from '@splunk/react-ui/Number';
import Text from '@splunk/react-ui/Text';
import { createDOMID } from '@splunk/ui-utils/id';
import P from '@splunk/react-ui/Paragraph';
import VarbindsCreator from "./VarbindsCreator";
import Conditions from "./Conditions";
import VarBinds from "./VarBinds";
import Condition from "./Condition";
import axios from "axios";
import ProfileContext from "../../store/profile-contxt";
import validateProfiles from "../validation/ValidateProfiles";
Expand All @@ -21,16 +21,7 @@ function AddProfileModal(props) {
const ProfCtx = useContext(ProfileContext);
const ValCtx = useContext(ProfilesValidationContxt);
const ErrCtx = useContext(ErrorsModalContext);
const [newSubmitPatterns, setNewSubmitPatterns] = useState(false);
const [newSubmitVarBinds, setNewSubmitVarBinds] = useState(false);

const newSubmitPatternsHandler = () =>{
setNewSubmitPatterns(!newSubmitPatterns);
};

const newSubmitVarBindsHandler = () =>{
setNewSubmitVarBinds(!newSubmitVarBinds);
};
const [newSubmit, setNewSubmit] = useState(false);


const handleProfileName = useCallback((e, { value: val }) => {
Expand All @@ -41,14 +32,6 @@ function AddProfileModal(props) {
ProfCtx.setFrequency(val);
}, []);

const handleVarBinds = (value) => {
ProfCtx.setVarBinds(value);
}

const handleConditions = (value) => {
ProfCtx.setConditions(value);
}

const postProfile = (profileObj) => {
axios.post(`http://${backendHost}/profiles/add`, profileObj)
.then((response) => {
Expand Down Expand Up @@ -91,11 +74,16 @@ function AddProfileModal(props) {
const handleApply = useCallback(
(e) => {

let profileObj = {
const profileObj = {
profileName: ProfCtx.profileName,
frequency: ProfCtx.frequency,
varBinds: ProfCtx.varBinds,
conditions: ProfCtx.conditions
conditions: {
condition: ProfCtx.condition,
field: ProfCtx.conditionField,
patterns: ProfCtx.conditionPatterns,
conditions: ProfCtx.conditional
}
};

const validation = validateProfiles(profileObj);
Expand All @@ -112,16 +100,16 @@ function AddProfileModal(props) {
ProfCtx.addModalToggle?.current?.focus();
}else{
// form is invalid
setNewSubmitPatterns(prevNewSubmitPatterns => {return !prevNewSubmitPatterns;});
setNewSubmitVarBinds(prevNewSubmitVarBinds => {return !prevNewSubmitVarBinds;});
setNewSubmit(prevNewSubmitPatterns => {return !prevNewSubmitPatterns;});
const errors = validation[1];
for (const property in errors) {
if (errors[property].length > 0 || Object.keys(errors[property]).length > 0){
ValCtx.setErrors(property, errors[property]);
const errorKeys = Object.keys(errors);
errorKeys.forEach((errorKey) => {
if (errors[errorKey].length > 0 || Object.keys(errors[errorKey]).length > 0){
ValCtx.setErrors(errorKey, errors[errorKey]);
}else {
ValCtx.resetErrors(property);
ValCtx.resetErrors(errorKey);
};
};
})
};

},
Expand Down Expand Up @@ -150,14 +138,15 @@ function AddProfileModal(props) {
</div>
</StyledControlGroup>

<Conditions onConditionsCreator={handleConditions} value={ProfCtx.conditions} errorField={ValCtx.conditionFieldErrors}
errorPatterns={ValCtx.conditionPatternsErrors} setErrorPatterns={ValCtx.setConditionPatternsErrors}
validationMessage={validationMessage} validationGroup={validationGroup} newSubmit={newSubmitPatterns}/>
<Condition newSubmit={newSubmit}/>

<StyledControlGroup label="VarBinds">
<VarbindsCreator onVarbindsCreator={handleVarBinds} value={ProfCtx.varBinds} error={ValCtx.varBindsErrors} setError={ValCtx.setVarBindsErrors}
validationMessage={validationMessage} validationGroup={validationGroup}
newSubmit={newSubmitVarBinds}/>
<div style={validationGroup}>
<VarBinds newSubmit={newSubmit}/>
{((ValCtx.varBindsExistErrors) ?
<P key={createDOMID()} style={validationMessage}>{ValCtx.varBindsExistErrors}</P>
: null)}
</div>
</StyledControlGroup>

</StyledModalBody>
Expand Down
74 changes: 74 additions & 0 deletions frontend/packages/manager/src/components/profiles/Condition.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, {useState, useRef, useCallback, useContext, useEffect} from 'react';
import { createDOMID } from '@splunk/ui-utils/id';
import ProfileContext from "../../store/profile-contxt";
import {StyledControlGroup} from "../../styles/inventory/InventoryStyle";
import Select from "@splunk/react-ui/Select";
import Text from "@splunk/react-ui/Text";
import P from "@splunk/react-ui/Paragraph";
import FieldPatterns from "./FieldPatterns";
import {validationGroup, validationMessage} from "../../styles/ValidationStyles";
import ProfilesValidationContxt from "../../store/profiles-validation-contxt";
import Conditional from "./Conditional";

function Condition(props){
const ProfCtx = useContext(ProfileContext);
const ValCtx = useContext(ProfilesValidationContxt);

const handleFieldChange = useCallback((e, { value: val }) => {
ProfCtx.setConditionField(val);
}, []);

const handleChange = useCallback((e, { value: val }) => {
ProfCtx.setCondition(val);
}, []);

return(
<div>
<StyledControlGroup label="Profile type"
labelFor="customized-select-after">
<Select value={ProfCtx.condition} onChange={handleChange} filter>
<Select.Option label="standard" value="standard"/>
<Select.Option label="base" value="base"/>
<Select.Option label="smart" value="smart"/>
<Select.Option label="walk" value="walk"/>
<Select.Option label="conditional" value="conditional"/>
</Select>
</StyledControlGroup>
{
ProfCtx.condition === 'smart' ? (
<div>
<StyledControlGroup label="Field">
<div style={validationGroup}>
<Text value={ProfCtx.conditionField} onChange={handleFieldChange} error={((ValCtx.conditionFieldErrors) ? true : false)}/>
{((ValCtx.conditionFieldErrors) ? ValCtx.conditionFieldErrors.map((el) =>
<P key={createDOMID()} style={validationMessage}>{el}</P>) : <P/>)}
</div>
</StyledControlGroup>
<StyledControlGroup label="Patterns">
<div style={validationGroup}>
<FieldPatterns newSubmit={props.newSubmit}/>
{((ValCtx.patternsExistErrors) ?
<P key={createDOMID()} style={validationMessage}>{ValCtx.patternsExistErrors}</P>
: null)}
</div>
</StyledControlGroup>
</div>) : null
}

{
ProfCtx.condition === 'conditional' ? (
<StyledControlGroup label="Conditions">
<div style={validationGroup}>
<Conditional newSubmit={props.newSubmit}/>
{((ValCtx.conditionalExistErrors) ?
<P key={createDOMID()} style={validationMessage}>{ValCtx.conditionalExistErrors}</P>
: null)}
</div>
</StyledControlGroup>
) : null
}
</div>
)
}

export default Condition;
Loading

0 comments on commit 564830a

Please sign in to comment.