Skip to content

Commit

Permalink
Modified translator ignore (rather than throw exceptions) when: (a) a…
Browse files Browse the repository at this point in the history
…n SLO contains an empty constraint, (b) the 'spec.scopes' section in a metric model is missing. Also commented out the metric model validator.
  • Loading branch information
ipatini committed Jan 9, 2025
1 parent ae9e808 commit da7efc8
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,12 @@ private TranslationContext translate(Object modelObj, String modelFileName, Stri
}

// -- Schematron Validation -------------------------------------------
log.debug("NebulousEmsTranslator.translate(): Validating metric model: {}", modelName);
//XXX:TODO: Replace with a JsonSchema validator
/*log.debug("NebulousEmsTranslator.translate(): Validating metric model: {}", modelName);
if (!properties.isSkipModelValidation()) {
validator.validateModel(modelObj, modelName);
log.debug("MetricModelAnalyzer.analyzeModel(): Metric model is valid: {}", modelName);
}
}*/

// -- Analyze metric model --------------------------------------------
log.debug("NebulousEmsTranslator.translate(): Analyzing model...");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.stereotype.Service;

import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -71,6 +72,30 @@ static Map<String, Object> asMap(Object o) {
throw createException("Object is not a Map: "+o);
}

static boolean isList(Object o) {
return (o instanceof List);
}

static boolean isMap(Object o) {
return (o instanceof Map);
}

static boolean isNullOrEmpty(Object o) {
if (o instanceof Collection c)
return isNullOrEmpty(c);
if (o instanceof Map m)
return isNullOrEmpty(m);
return (o==null);
}

static boolean isNullOrEmpty(Collection c) {
return (c==null || c.isEmpty());
}

static boolean isNullOrEmpty(Map m) {
return (m==null || m.isEmpty());
}

// ------------------------------------------------------------------------
// Name and Field methods
// ------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,27 @@ public void analyzeModel(@NonNull TranslationContext _TC, @NonNull Object metric
});
}

// ----- Check if component and scope specifications exist -----
log.debug("MetricModelAnalyzer.analyzeModel(): Checking for component and scope specs");
Map specs = ctx.read("$.spec", Map.class);
if (log.isDebugEnabled()) {
log.debug("MetricModelAnalyzer.analyzeModel(): spec.components: {}", specs.get("components"));
log.debug("MetricModelAnalyzer.analyzeModel(): spec.scopes: {}", specs.get("scopes"));
}
boolean hasComponents = ! isNullOrEmpty(specs.get("components"));
boolean hasScopes = ! isNullOrEmpty(specs.get("scopes"));
log.debug("Has component specs: {}", hasComponents);
log.debug("Has scope specs : {}", hasScopes);
if (! hasComponents && ! hasScopes)
throw createException("Metric model contains no component and no scope specifications");
if (hasScopes && !hasComponents)
throw createException("Metric model contains no components but has scope specifications");

// ----- Get component and scope names -----
log.debug("MetricModelAnalyzer.analyzeModel(): Check name uniqueness");
List<String> componentNamesList = ctx.read("$.spec.components.*.name", List.class);
List<String> scopeNamesList = ctx.read("$.spec.scopes.*.name", List.class);
List<String> scopeNamesList = hasScopes
? ctx.read("$.spec.scopes.*.name", List.class) : Collections.emptyList();
log.debug("Component names: {}", componentNamesList);
log.debug(" Scope names: {}", scopeNamesList);

Expand Down Expand Up @@ -116,7 +133,8 @@ public void analyzeModel(@NonNull TranslationContext _TC, @NonNull Object metric
log.debug(" All SLOs: {}", $$(_TC).allSLOs);

// ----- Build scope-to-components map -----
$$(_TC).scopesComponents = nodeUpdatingHelper.createScopesToComponentsMap(ctx, componentNames);
$$(_TC).scopesComponents = hasScopes
? nodeUpdatingHelper.createScopesToComponentsMap(ctx, componentNames) : Collections.emptyMap();

// ----- Build of constants lists -----
log.debug("MetricModelAnalyzer.analyzeModel(): Build constants list");
Expand Down Expand Up @@ -298,7 +316,14 @@ private void buildElementLists(TranslationContext _TC, Map<String, Object> model
log.debug("buildElementLists: SLO (requirements): {}", sloSpec);
String sloName = getSpecName(sloSpec);
if (StringUtils.isBlank(sloName)) throw createException("SLO spec with no name: " + sloSpec);
$$(_TC).allSLOs.put(createNamesKey(parentName, sloName), sloSpec);
Object constraintObject = asMap(sloSpec).get("constraint");
/*if (!isMap(constraintObject) || asMap(constraintObject).isEmpty())
throw createException("SLO spec with no constraint: " + sloSpec);*/
if (isMap(constraintObject) && ! asMap(constraintObject).isEmpty()) {
$$(_TC).allSLOs.put(createNamesKey(parentName, sloName), sloSpec);
} else {
log.warn("Ignoring SLO with no or empty constraint: {}", sloSpec);
}
});

// Constraints flat list building
Expand All @@ -308,9 +333,14 @@ private void buildElementLists(TranslationContext _TC, Map<String, Object> model
if (StringUtils.isBlank(sloName)) throw createException("SLO spec with no name: " + sloSpec);

NamesKey sloNamesKey = createNamesKey(parentName, sloName);
Map<String, Object> constraintSpec = asMap(asMap(sloSpec).get("constraint"));
NamesKey constraintNamesKey = createNamesKey(sloNamesKey, sloName);
$$(_TC).allConstraints.put(constraintNamesKey, constraintSpec);
Object constraintObject = asMap(sloSpec).get("constraint");
if (isMap(constraintObject)) {
Map<String, Object> constraintSpec = asMap(constraintObject);
NamesKey constraintNamesKey = createNamesKey(sloNamesKey, sloName);
$$(_TC).allConstraints.put(constraintNamesKey, constraintSpec);
} else {
log.warn("Ignored SLO with no or empty constraint: {}", sloName);
}
});

// Metrics flat list building
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ void buildComponentsToSLOsMap(TranslationContext _TC, DocumentContext ctx, Set<S
}

Map<String, Set<String>> createComponentsToScopesMap(DocumentContext ctx, Set<String> componentNames) {
Map specs = ctx.read("$.spec", Map.class);
if (isNullOrEmpty(specs.get("scopes")))
return Collections.emptyMap();

Map<String, Set<String>> componentToScopeMap = new LinkedHashMap<>();
ctx.read("$.spec.scopes.*", List.class).stream().filter(Objects::nonNull).forEach(scope -> {
// Get scope name and scope components
Expand Down Expand Up @@ -107,6 +111,10 @@ Map<String, Set<String>> createComponentsToScopesMap(DocumentContext ctx, Set<St
}

Map<String, Set<String>> createScopesToComponentsMap(DocumentContext ctx, Set<String> componentNames) {
Map specs = ctx.read("$.spec", Map.class);
if (isNullOrEmpty(specs.get("scopes")))
return Collections.emptyMap();

Map<String, Set<String>> scopeToComponentMap = new LinkedHashMap<>();
ctx.read("$.spec.scopes.*", List.class).stream().filter(Objects::nonNull).forEach(scope -> {
// Get scope name and scope components
Expand Down

0 comments on commit da7efc8

Please sign in to comment.