From d99570740e1658866b625e905defb353a05678c1 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Wed, 9 Jun 2021 12:27:38 +0200 Subject: [PATCH 001/310] [#565] csv input can read relations --- .../nivio/input/InputFormatHandler.java | 2 +- .../compose2/InputFormatHandlerCompose2.java | 5 +- .../input/csv/InputFormatHandlerCSV.java | 55 ++++++++++++------- .../input/dot/InputFormatHandlerDot.java | 2 +- .../nivio/input/dto/GroupDescription.java | 8 +-- .../nivio/input/dto/ItemDescription.java | 1 + .../nivio/input/dto/LandscapeDescription.java | 7 +-- .../nivio/input/dto/RelationDescription.java | 29 +++++++++- .../InputFormatHandlerKubernetes.java | 2 +- .../input/nivio/InputFormatHandlerNivio.java | 5 +- .../rancher1/InputFormatHandlerRancher1.java | 5 +- .../InputFormatHandlerRancher1API.java | 5 +- .../de/bonndan/nivio/model/Component.java | 2 - .../java/de/bonndan/nivio/model/Group.java | 6 -- .../java/de/bonndan/nivio/model/Item.java | 1 + .../de/bonndan/nivio/model/ItemComponent.java | 3 + .../java/de/bonndan/nivio/model/Labeled.java | 1 + .../de/bonndan/nivio/model/Landscape.java | 7 +-- .../java/de/bonndan/nivio/model/Relation.java | 38 ++++++++----- .../nivio/assessment/AssessableTest.java | 5 -- .../input/csv/InputFormatHandlerCSVTest.java | 36 ++++++++++++ .../example/services/test_relation.csv | 2 + 22 files changed, 149 insertions(+), 78 deletions(-) create mode 100644 src/test/resources/example/services/test_relation.csv diff --git a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java index a3f32174d..8f1236f69 100644 --- a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java +++ b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java @@ -28,7 +28,7 @@ public interface InputFormatHandler { * @param baseUrl parent config url * @param landscapeDescription the input dto to modify */ - void applyData(SourceReference reference, @Nullable URL baseUrl, LandscapeDescription landscapeDescription); + void applyData(@NonNull final SourceReference reference, @Nullable URL baseUrl, LandscapeDescription landscapeDescription); /** * Returns an observer for the source reference. diff --git a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java index 4e3477765..c4624d70d 100644 --- a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java +++ b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java @@ -13,6 +13,7 @@ import de.bonndan.nivio.observation.InputFormatObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.io.IOException; @@ -49,7 +50,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String yml = fileFetcher.get(reference, baseUrl); @@ -73,7 +74,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { + public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { return inner; } diff --git a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java index a9ea21d81..cae2bf72f 100644 --- a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java +++ b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java @@ -10,22 +10,20 @@ import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Relation; import de.bonndan.nivio.observation.InputFormatObserver; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.StringReader; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * Reads csv files to {@link ItemDescription}s. - * - * */ @Service public class InputFormatHandlerCSV implements InputFormatHandler { @@ -44,7 +42,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String content = fileFetcher.get(reference, baseUrl); CSVReader reader = getReader(reference, content); @@ -54,33 +52,48 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti throw new ProcessingException(reference.getLandscapeDescription(), "'mapping' must be present in configuration."); } if (!mapping.containsKey(IDENTIFIER_KEY)) { - throw new ProcessingException(reference.getLandscapeDescription(), "'" + IDENTIFIER_KEY + "' must be present in configured mapping."); + throw new ProcessingException(reference.getLandscapeDescription(), String.format("'%s' must be present in configured mapping.", IDENTIFIER_KEY)); } reader.iterator().forEachRemaining(strings -> { ItemDescription itemDescription = new ItemDescription(); - mapping.forEach((key, value) -> { - Integer colNum = 0; + RelationDescription relationDescription = null; + Map labels = new HashMap<>(); + for (Map.Entry entry : mapping.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + int colNum = 0; if (value instanceof String) { - colNum = Integer.valueOf((String)value); + colNum = Integer.parseInt((String) value); } if (value instanceof Integer) { colNum = (Integer) value; } - + String columnValue = strings[colNum]; if (IDENTIFIER_KEY.equals(key)) { - itemDescription.setIdentifier(strings[colNum]); - return; - } - - if (colNum >= strings.length) { - return; + if (columnValue.contains(Relation.DELIMITER)) { + String[] split = columnValue.split(Relation.DELIMITER); + itemDescription.setIdentifier(split[0]); + relationDescription = new RelationDescription(split[0], split[1]); + } else { + + itemDescription.setIdentifier(columnValue); + } + continue; } //relies on LabelToFieldProcessor running later - itemDescription.getLabels().put(LabelToFieldResolver.NIVIO_LABEL_PREFIX + key, strings[colNum]); - }); + labels.put(LabelToFieldResolver.NIVIO_LABEL_PREFIX + key, columnValue); + } + + if (relationDescription != null) { + relationDescription.setLabels(labels); + itemDescription.addRelation(relationDescription); + } else { + itemDescription.getLabels().putAll(labels); + } + itemDescriptions.add(itemDescription); }); @@ -89,7 +102,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti @Override @Nullable - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { + public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { return inner; } diff --git a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java index 760c4f904..1357e79ce 100644 --- a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java +++ b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java @@ -43,7 +43,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String content = fileFetcher.get(reference, baseUrl); List items = new ArrayList<>(); diff --git a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java index 22739e564..008b65095 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java @@ -6,6 +6,7 @@ import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.Link; import io.swagger.v3.oas.annotations.media.Schema; +import org.springframework.lang.NonNull; import java.util.ArrayList; import java.util.HashMap; @@ -74,12 +75,6 @@ public String getIcon() { return null; } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - public void setOwner(String owner) { this.owner = owner; } @@ -131,6 +126,7 @@ public void setContains(List contains) { this.contains = contains; } + @NonNull public Map getLabels() { return labels; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index cce9fe8ac..781200619 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -195,6 +195,7 @@ public void setLifecycle(String lifecycle) { } } + @NonNull @Override public Map getLabels() { return labels; diff --git a/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java b/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java index 83c103baf..8b0950293 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java @@ -174,12 +174,6 @@ public void setSource(LandscapeSource source) { this.source = source; } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - public ItemIndex getItemDescriptions() { return itemDescriptions; } @@ -287,6 +281,7 @@ public Map getLinks() { return links; } + @NonNull public Map getLabels() { return labels; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 47198a9bb..3c0a3b94d 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -1,10 +1,15 @@ package de.bonndan.nivio.input.dto; +import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.RelationType; import io.swagger.v3.oas.annotations.media.Schema; +import org.springframework.lang.NonNull; + +import java.util.HashMap; +import java.util.Map; @Schema(description = "A directed relation between two landscape items. Also known as edge in a directed graph.") -public class RelationDescription { +public class RelationDescription implements Labeled { @Schema(description = "The type of the relation, i.e. whether it is a hard or a soft dependency.") private RelationType type; @@ -21,7 +26,11 @@ public class RelationDescription { @Schema(description = "The item identifier of the target. Prepend a group identifier if the simple item identifier is ambiguous.", example = "dataSink|groupB/dataSink") private String target; - public RelationDescription(){} + @Schema(description = "Key-value pair labels for a relation.") + private final Map labels = new HashMap<>(); + + public RelationDescription() { + } public RelationDescription(String source, String target) { this.source = source; @@ -78,4 +87,20 @@ public String toString() { ", target='" + target + '\'' + '}'; } + + @Override + public String getLabel(String key) { + return getLabels().get(key); + } + + @Override + @NonNull + public Map getLabels() { + return labels; + } + + @Override + public void setLabel(String key, String value) { + getLabels().put(key, value); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index e20ea45b8..dd183ba2e 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -60,7 +60,7 @@ public List getFormats() { * Created Items: service -> pod -> containers */ @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { try { if (!StringUtils.isEmpty(reference.getUrl())) { diff --git a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java index 94cb8d027..c629403a3 100644 --- a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java +++ b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java @@ -11,6 +11,7 @@ import de.bonndan.nivio.input.Mappers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; @@ -41,7 +42,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription description) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription description) { List descriptions = new ArrayList<>(); String yml = fileFetcher.get(reference, baseUrl); @@ -69,7 +70,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti @Override @Nullable - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { + public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { return inner; } } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java index 57c21c413..6187c9ddc 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java @@ -8,6 +8,7 @@ import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.net.MalformedURLException; @@ -27,7 +28,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { String landscape = reference.getLandscapeDescription().getIdentifier(); @@ -42,7 +43,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { + public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { //TODO add observer return null; } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java index b356f327e..d9431e3dd 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java @@ -8,6 +8,7 @@ import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.observation.InputFormatObserver; import io.rancher.Rancher; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -28,13 +29,13 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { APIWalker apiWalker = new APIWalker(reference, getConfig(reference)); landscapeDescription.mergeItems(apiWalker.getDescriptions()); } @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference reference) { + public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference reference) { Rancher.Config config = getConfig(reference); //TODO add observer return null; diff --git a/src/main/java/de/bonndan/nivio/model/Component.java b/src/main/java/de/bonndan/nivio/model/Component.java index 4b191fcf1..88cc9cc65 100644 --- a/src/main/java/de/bonndan/nivio/model/Component.java +++ b/src/main/java/de/bonndan/nivio/model/Component.java @@ -60,6 +60,4 @@ public interface Component { @Nullable String getColor(); - @Nullable - String getAddress(); } diff --git a/src/main/java/de/bonndan/nivio/model/Group.java b/src/main/java/de/bonndan/nivio/model/Group.java index 617a4049f..77494fdb6 100644 --- a/src/main/java/de/bonndan/nivio/model/Group.java +++ b/src/main/java/de/bonndan/nivio/model/Group.java @@ -127,12 +127,6 @@ public String getColor() { return color; } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - @Schema(name = "_links") public Map getLinks() { return links; diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 9f8583c87..abdb1c954 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -150,6 +150,7 @@ public String getDescription() { return description; } + @NonNull @JsonIgnore @Override public Map getLabels() { diff --git a/src/main/java/de/bonndan/nivio/model/ItemComponent.java b/src/main/java/de/bonndan/nivio/model/ItemComponent.java index b3194c795..9e7ae9356 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemComponent.java +++ b/src/main/java/de/bonndan/nivio/model/ItemComponent.java @@ -11,4 +11,7 @@ public interface ItemComponent extends Component { @Nullable String getGroup(); + + @Nullable + String getAddress(); } diff --git a/src/main/java/de/bonndan/nivio/model/Labeled.java b/src/main/java/de/bonndan/nivio/model/Labeled.java index 03491dabd..e5f624a5b 100644 --- a/src/main/java/de/bonndan/nivio/model/Labeled.java +++ b/src/main/java/de/bonndan/nivio/model/Labeled.java @@ -61,6 +61,7 @@ default Map getLabels(Label prefix) { /** * Returns all label with values. */ + @NonNull Map getLabels(); void setLabel(String key, String value); diff --git a/src/main/java/de/bonndan/nivio/model/Landscape.java b/src/main/java/de/bonndan/nivio/model/Landscape.java index d945d08d5..185630612 100644 --- a/src/main/java/de/bonndan/nivio/model/Landscape.java +++ b/src/main/java/de/bonndan/nivio/model/Landscape.java @@ -161,12 +161,6 @@ public Collection getGroupItems() { return new ArrayList<>(groups.values()); } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -223,6 +217,7 @@ public String getOwner() { return owner; } + @NonNull @JsonIgnore @Override public Map getLabels() { diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index aa8ba3d67..38548c1dc 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -1,15 +1,13 @@ package de.bonndan.nivio.model; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonInclude; import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import static de.bonndan.nivio.model.ComponentDiff.compareOptionals; import static de.bonndan.nivio.model.ComponentDiff.compareStrings; @@ -17,11 +15,10 @@ /** * Indication of an incoming or outgoing relation like data flow or dependency (provider). * - *

* Outgoing flows having a target which matches a service identifier will cause a relation to be created. */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class Relation implements Serializable { +public class Relation implements Labeled, Serializable { public static final String DELIMITER = ";"; @@ -37,6 +34,8 @@ public class Relation implements Serializable { private final RelationType type; + private final Map labels = new HashMap<>(); + public Relation(@NonNull final Item source, @NonNull final Item target ) { @@ -49,16 +48,12 @@ public Relation(@NonNull final Item source, final String format, final RelationType type ) { - if (source == null || target == null) { - throw new IllegalArgumentException("Null arguments passed."); - } - if (source.equals(target)) { throw new IllegalArgumentException("Relation source and target are equal."); } - this.source = source; - this.target = target; + this.source = Objects.requireNonNull(source, "Source is null"); + this.target = Objects.requireNonNull(target, "Target is null"); this.description = description; this.format = format; this.type = type; @@ -107,6 +102,23 @@ public String toString() { return "Relation{" + getIdentifier() + '}'; } + @Override + public String getLabel(String key) { + return getLabels().get(key); + } + + @NonNull + @Override + public Map getLabels() { + return labels; + } + + @Override + @JsonAnySetter + public void setLabel(String key, String value) { + labels.put(key, value); + } + @JsonInclude(JsonInclude.Include.NON_NULL) static class ApiModel { @@ -158,7 +170,7 @@ static class ApiModel { */ public List getChanges(Relation newer) { if (!newer.equals(this)) { - throw new IllegalArgumentException("Cannot compare relation " + newer.toString() + " against " + this.toString()); + throw new IllegalArgumentException(String.format("Cannot compare relation %s against %s", newer, this)); } List changes = new ArrayList<>(); diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java index 57b28fc8b..70d758392 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java @@ -265,11 +265,6 @@ public String getColor() { return null; } - @Override - public String getAddress() { - return null; - } - @Override public List getChildren() { return children; diff --git a/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java b/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java index ca2a0b55b..bd7da4057 100644 --- a/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java +++ b/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java @@ -4,6 +4,7 @@ import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.http.HttpService; import de.bonndan.nivio.observation.InputFormatObserver; @@ -17,6 +18,7 @@ import java.util.List; import java.util.Map; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -77,6 +79,40 @@ public void read() { assertEquals("superior", super1.getLabels().get("nivio.description")); } + @Test + public void readRelationDescriptions() { + + SourceReference file = SourceReference.of(new File(getRootPath() + "/src/test/resources/example/services/test_relation.csv")); + + Map mapping = new HashMap<>(); + mapping.put("identifier", "1"); + mapping.put("name", "0"); + mapping.put("foo", "2"); + mapping.put("bar", "3"); + file.setProperty("mapping", mapping); + file.setProperty("skipLines", 1); + file.setProperty("separator", ";"); + + InputFormatHandlerCSV factoryCSV = new InputFormatHandlerCSV(fileFetcher); + LandscapeDescription landscapeDescription = new LandscapeDescription("test"); + + //when + factoryCSV.applyData(file, null, landscapeDescription); + + //then + assertEquals(1, landscapeDescription.getItemDescriptions().all().size()); + ItemDescription foo = landscapeDescription.getItemDescriptions().pick("foo", null); + assertNotNull(foo); + + assertThat(foo.getRelations()).hasSize(1).satisfies(relationDescriptions -> { + RelationDescription next = relationDescriptions.iterator().next(); + assertThat(next.getSource()).isEqualTo("foo"); + assertThat(next.getTarget()).isEqualTo("bar"); + assertThat(next.getLabel("nivio.name")).isEqualTo("a relation"); + assertThat(next.getLabel("nivio.foo")).isEqualTo("This does nothing"); + }); + } + @Test public void failsWithoutMapping() { diff --git a/src/test/resources/example/services/test_relation.csv b/src/test/resources/example/services/test_relation.csv new file mode 100644 index 000000000..079009714 --- /dev/null +++ b/src/test/resources/example/services/test_relation.csv @@ -0,0 +1,2 @@ +service;id;desc;targets +"a relation";"foo;bar";This does nothing; From 3729169a9116ea0b95acf3be1d86c88089cd0751 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:23:04 +0200 Subject: [PATCH 002/310] add new environment variables --- src/main/resources/application.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fc7aa19eb..b4dd220cd 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -47,6 +47,20 @@ nivio: brandingBackground: ${NIVIO_BRANDING_BACKGROUND:161618} brandingSecondary: ${NIVIO_BRANDING_SECONDARY:22F2C2} brandingLogoUrl: ${NIVIO_BRANDING_LOGO_URL:} + seed: ${SEED:} # add a new environment variable + + gitlab: # add new environment variables + hostUrl: ${GITLAB_HOST_URL:} + personalAccessToken: ${GITLAB_PERSONAL_ACCESS_TOKEN:} + username: ${GITLAB_USERNAME:} + password: ${GITLAB_PASSWORD:} + + sonar: # add new environment variables + serverUrl: ${SONAR_SERVER_URL:} + login: ${SONAR_LOGIN:} + password: ${SONAR_PASSWORD:} + proxyHost: ${SONAR_PROXY_HOST:} + proxyPort: ${SONAR_PROXY_PORT:} --- spring: From 78e1ee3d6fc7e6e3d9b954d158a8780572fa5553 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:30:18 +0200 Subject: [PATCH 003/310] create a new class of the environment variable SEED --- .../bonndan/nivio/config/SeedProperties.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/config/SeedProperties.java diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java new file mode 100644 index 000000000..2a36eaa39 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -0,0 +1,19 @@ +package de.bonndan.nivio.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "nivio") +@Validated +public class SeedProperties { + public String getSeed() { + return seed; + } + + public void setSeed(String seed) { + this.seed = seed; + } + + private String seed; + +} From 1560f56c9cd2dfd80472b067a14016a3fb856374 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:31:59 +0200 Subject: [PATCH 004/310] add a new attribute of type SeedProperties and a constructor --- .../de/bonndan/nivio/config/ApplicationConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index b9853362e..50e8205bf 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -2,7 +2,9 @@ import de.bonndan.nivio.input.Seed; import de.bonndan.nivio.output.icons.LocalIcons; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @@ -12,8 +14,16 @@ import static de.bonndan.nivio.output.icons.LocalIcons.DEFAULT_ICONS_FOLDER; @Configuration +@EnableConfigurationProperties(SeedProperties.class) public class ApplicationConfig { + private final SeedProperties seedProperties; + + @Autowired + public ApplicationConfig(SeedProperties seedProperties) { + this.seedProperties = seedProperties; + } + @Bean public WebMvcConfigurer configurer() { return new WebMvcConfigurer() { From b84c22ef0023302ec1977c2361defe36ba772ee3 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:41:22 +0200 Subject: [PATCH 005/310] create a new class of the environment variables SONAR --- .../input/external/sonar/SonarProperties.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java new file mode 100644 index 000000000..e46fae3a1 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.input.external.sonar; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "sonar") +@Validated + +public class SonarProperties { + + public String getServerUrl() { + return serverUrl; + } + + public void setServerUrl(String serverUrl) { + this.serverUrl = serverUrl; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public String getProxyPort() { + return proxyPort; + } + + public void setProxyPort(String proxyPort) { + this.proxyPort = proxyPort; + } + + private String serverUrl; + private String login; + private String password; + private String proxyHost; + private String proxyPort; + + + +} From 91024f17dad1bb0211d3326b4b8f6f42aa05d5d3 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:42:26 +0200 Subject: [PATCH 006/310] add a new variable of typ SonarProperties and a constructor --- .../nivio/input/external/sonar/SonarConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java index ecb2e3cb5..703922db5 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java @@ -1,6 +1,8 @@ package de.bonndan.nivio.input.external.sonar; import org.sonar.wsclient.SonarClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -9,8 +11,16 @@ import static de.bonndan.nivio.config.ConfigurableEnvVars.*; @Configuration +@EnableConfigurationProperties(SonarProperties.class) public class SonarConfig { + private final SonarProperties sonarProperties; + + @Autowired + public SonarConfig(SonarProperties sonarProperties) { + this.sonarProperties = sonarProperties; + } + @Bean public SonarClient.Builder getSonarClientBuilder() { From 6bbf906247f0318933795c194b0b32b8b62b5771 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:46:38 +0200 Subject: [PATCH 007/310] create a new class of the environment variables GITLAB --- .../external/gitlab/GitLabProperties.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java new file mode 100644 index 000000000..b6017dd4d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -0,0 +1,47 @@ +package de.bonndan.nivio.input.external.gitlab; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "gitlab") +@Validated +public class GitLabProperties { + + public String getHostUrl() { + return hostUrl; + } + + public void setHostUrl(String hostUrl) { + this.hostUrl = hostUrl; + } + + public String getPersonalAccessToken() { + return personalAccessToken; + } + + public void setPersonalAccessToken(String personalAccessToken) { + this.personalAccessToken = personalAccessToken; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + private String hostUrl; + private String personalAccessToken; + private String username; + private String password; + +} From c614df82b8e311962367218f194119f71c94f2e8 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:52:15 +0200 Subject: [PATCH 008/310] add a new variable of typ GitLabProperties and a constructor --- .../nivio/input/external/gitlab/GitLabConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java index 51bf78b11..d0342ca57 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java @@ -1,6 +1,8 @@ package de.bonndan.nivio.input.external.gitlab; import org.gitlab4j.api.GitLabApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.lang.NonNull; @@ -11,8 +13,16 @@ @Configuration +@EnableConfigurationProperties(GitLabProperties.class) public class GitLabConfig { + private final GitLabProperties gitLabProperties; + + @Autowired + public GitLabConfig(GitLabProperties gitLabProperties) { + this.gitLabProperties = gitLabProperties; + } + @Bean public GitLabApi getGitLabAPI() { From eec1b32ff25a2f4224cd84762fea8ed2daae1e2b Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:23:04 +0200 Subject: [PATCH 009/310] add new environment variables --- src/main/resources/application.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 343193418..ada6556bf 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -48,6 +48,22 @@ nivio: brandingSecondary: ${NIVIO_BRANDING_SECONDARY:22F2C2} brandingLogoUrl: ${NIVIO_BRANDING_LOGO_URL:} brandingMessage: ${NIVIO_BRANDING_MESSAGE:All Landscapes} + seed: ${SEED:} # add a new environment variable + + +gitlab: # add new environment variables + hostUrl: ${GITLAB_HOST_URL:} + personalAccessToken: ${GITLAB_PERSONAL_ACCESS_TOKEN:} + username: ${GITLAB_USERNAME:} + password: ${GITLAB_PASSWORD:} + + +sonar: # add new environment variables + serverUrl: ${SONAR_SERVER_URL:} + login: ${SONAR_LOGIN:} + password: ${SONAR_PASSWORD:} + proxyHost: ${SONAR_PROXY_HOST:} + proxyPort: ${SONAR_PROXY_PORT:} --- spring: From f5d3041d093f6973875da5170059b344aebaa9a1 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:30:18 +0200 Subject: [PATCH 010/310] create a new class of the environment variable SEED --- .../bonndan/nivio/config/SeedProperties.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/config/SeedProperties.java diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java new file mode 100644 index 000000000..2a36eaa39 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -0,0 +1,19 @@ +package de.bonndan.nivio.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "nivio") +@Validated +public class SeedProperties { + public String getSeed() { + return seed; + } + + public void setSeed(String seed) { + this.seed = seed; + } + + private String seed; + +} From 143d765641fde6d8ae0e2d328197461521af08a7 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:31:59 +0200 Subject: [PATCH 011/310] add a new attribute of type SeedProperties and a constructor --- .../de/bonndan/nivio/config/ApplicationConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index b9853362e..50e8205bf 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -2,7 +2,9 @@ import de.bonndan.nivio.input.Seed; import de.bonndan.nivio.output.icons.LocalIcons; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @@ -12,8 +14,16 @@ import static de.bonndan.nivio.output.icons.LocalIcons.DEFAULT_ICONS_FOLDER; @Configuration +@EnableConfigurationProperties(SeedProperties.class) public class ApplicationConfig { + private final SeedProperties seedProperties; + + @Autowired + public ApplicationConfig(SeedProperties seedProperties) { + this.seedProperties = seedProperties; + } + @Bean public WebMvcConfigurer configurer() { return new WebMvcConfigurer() { From 47e3d11000d00207a160bb9614e785e28ea8913c Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:41:22 +0200 Subject: [PATCH 012/310] create a new class of the environment variables SONAR --- .../input/external/sonar/SonarProperties.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java new file mode 100644 index 000000000..e46fae3a1 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.input.external.sonar; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "sonar") +@Validated + +public class SonarProperties { + + public String getServerUrl() { + return serverUrl; + } + + public void setServerUrl(String serverUrl) { + this.serverUrl = serverUrl; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public String getProxyPort() { + return proxyPort; + } + + public void setProxyPort(String proxyPort) { + this.proxyPort = proxyPort; + } + + private String serverUrl; + private String login; + private String password; + private String proxyHost; + private String proxyPort; + + + +} From c4911c10594746c4e83631b62aa3f25f5041fe59 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:42:26 +0200 Subject: [PATCH 013/310] add a new variable of typ SonarProperties and a constructor --- .../nivio/input/external/sonar/SonarConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java index ecb2e3cb5..703922db5 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java @@ -1,6 +1,8 @@ package de.bonndan.nivio.input.external.sonar; import org.sonar.wsclient.SonarClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -9,8 +11,16 @@ import static de.bonndan.nivio.config.ConfigurableEnvVars.*; @Configuration +@EnableConfigurationProperties(SonarProperties.class) public class SonarConfig { + private final SonarProperties sonarProperties; + + @Autowired + public SonarConfig(SonarProperties sonarProperties) { + this.sonarProperties = sonarProperties; + } + @Bean public SonarClient.Builder getSonarClientBuilder() { From 01fe4436436bbbf9dffc1c900103095055e6f939 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:46:38 +0200 Subject: [PATCH 014/310] create a new class of the environment variables GITLAB --- .../external/gitlab/GitLabProperties.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java new file mode 100644 index 000000000..b6017dd4d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -0,0 +1,47 @@ +package de.bonndan.nivio.input.external.gitlab; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "gitlab") +@Validated +public class GitLabProperties { + + public String getHostUrl() { + return hostUrl; + } + + public void setHostUrl(String hostUrl) { + this.hostUrl = hostUrl; + } + + public String getPersonalAccessToken() { + return personalAccessToken; + } + + public void setPersonalAccessToken(String personalAccessToken) { + this.personalAccessToken = personalAccessToken; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + private String hostUrl; + private String personalAccessToken; + private String username; + private String password; + +} From b0314fcb4d23aaac09a43854c97bc1ed4c37d850 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 9 Jun 2021 17:52:15 +0200 Subject: [PATCH 015/310] add a new variable of typ GitLabProperties and a constructor --- .../nivio/input/external/gitlab/GitLabConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java index 51bf78b11..d0342ca57 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java @@ -1,6 +1,8 @@ package de.bonndan.nivio.input.external.gitlab; import org.gitlab4j.api.GitLabApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.lang.NonNull; @@ -11,8 +13,16 @@ @Configuration +@EnableConfigurationProperties(GitLabProperties.class) public class GitLabConfig { + private final GitLabProperties gitLabProperties; + + @Autowired + public GitLabConfig(GitLabProperties gitLabProperties) { + this.gitLabProperties = gitLabProperties; + } + @Bean public GitLabApi getGitLabAPI() { From 6545e0b2be845fcef3cb207d7e4d5e349799e5d1 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 07:50:32 +0200 Subject: [PATCH 016/310] update with new environment variables --- application.yml | 0 .../external/github/GitHubProperties.java | 47 +++++++++++++++++++ src/main/resources/application.yml | 6 +++ 3 files changed, 53 insertions(+) create mode 100644 application.yml create mode 100644 src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java diff --git a/application.yml b/application.yml new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java new file mode 100644 index 000000000..2dc375645 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java @@ -0,0 +1,47 @@ +package de.bonndan.nivio.input.external.github; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "github") +@Validated + +public class GitHubProperties { + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getOauth() { + return oauth; + } + + public void setOauth(String oauth) { + this.oauth = oauth; + } + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + + private String login; + private String password; + private String oauth; + private String jwt; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ada6556bf..c63864f69 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -58,6 +58,12 @@ gitlab: # add new environment variables password: ${GITLAB_PASSWORD:} +github: # add new environment variables + login: ${GITHUB_LOGIN:} + password: ${GITHUB_PASSWORD:} + oauth: ${GITHUB_OAUTH:} + jwt: ${GITHUB_JWT:} + sonar: # add new environment variables serverUrl: ${SONAR_SERVER_URL:} login: ${SONAR_LOGIN:} From 1686d654e076334922883db6f6922dd78a13e928 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 07:57:54 +0200 Subject: [PATCH 017/310] update the class SeedProperties --- src/main/java/de/bonndan/nivio/config/SeedProperties.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index 2a36eaa39..d124f9414 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -4,8 +4,11 @@ import org.springframework.validation.annotation.Validated; @ConfigurationProperties(prefix = "nivio") -@Validated + public class SeedProperties { + + private String seed; + public String getSeed() { return seed; } @@ -14,6 +17,4 @@ public void setSeed(String seed) { this.seed = seed; } - private String seed; - } From 09dae9eecfe6e143a9093f4580af4698c9524d11 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:00:18 +0200 Subject: [PATCH 018/310] update the class ApplicationConfig and remove @Autowired --- .../java/de/bonndan/nivio/config/ApplicationConfig.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index 50e8205bf..06be8403f 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -2,7 +2,6 @@ import de.bonndan.nivio.input.Seed; import de.bonndan.nivio.output.icons.LocalIcons; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -11,6 +10,8 @@ import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.Optional; + import static de.bonndan.nivio.output.icons.LocalIcons.DEFAULT_ICONS_FOLDER; @Configuration @@ -19,7 +20,6 @@ public class ApplicationConfig { private final SeedProperties seedProperties; - @Autowired public ApplicationConfig(SeedProperties seedProperties) { this.seedProperties = seedProperties; } @@ -41,7 +41,8 @@ public RestTemplate restTemplate() { @Bean public Seed seed() { - return new Seed(ConfigurableEnvVars.SEED.value()); + + return new Seed(Optional.ofNullable(seedProperties.getSeed())); } @Bean From a1d0b0a46fbb3aaf8314d2cd24deb53f32e0036c Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:02:21 +0200 Subject: [PATCH 019/310] update the class SonarProperties and remove @Validated --- .../input/external/sonar/SonarProperties.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java index e46fae3a1..469c79a74 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -4,10 +4,16 @@ import org.springframework.validation.annotation.Validated; @ConfigurationProperties(prefix = "sonar") -@Validated + public class SonarProperties { + private String serverUrl; + private String login; + private String password; + private String proxyHost; + private String proxyPort; + public String getServerUrl() { return serverUrl; } @@ -48,11 +54,7 @@ public void setProxyPort(String proxyPort) { this.proxyPort = proxyPort; } - private String serverUrl; - private String login; - private String password; - private String proxyHost; - private String proxyPort; + From 6b8f48289b4a6204f11068f7ca00e42381a1d229 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:05:51 +0200 Subject: [PATCH 020/310] update the method getSonarBuilder() --- .../nivio/input/external/sonar/SonarConfig.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java index 703922db5..a8b2c2c94 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.input.external.sonar; import org.sonar.wsclient.SonarClient; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -9,6 +8,7 @@ import java.util.Optional; import static de.bonndan.nivio.config.ConfigurableEnvVars.*; +import java.util.Optional; @Configuration @EnableConfigurationProperties(SonarProperties.class) @@ -16,7 +16,6 @@ public class SonarConfig { private final SonarProperties sonarProperties; - @Autowired public SonarConfig(SonarProperties sonarProperties) { this.sonarProperties = sonarProperties; } @@ -24,16 +23,19 @@ public SonarConfig(SonarProperties sonarProperties) { @Bean public SonarClient.Builder getSonarClientBuilder() { - Optional serverUrl = SONAR_SERVER_URL.value(); + Optional serverUrl = Optional.ofNullable(sonarProperties.getServerUrl()); + if (serverUrl.isEmpty()) { return null; } SonarClient.Builder builder = SonarClient.builder().url(serverUrl.get()); - SONAR_LOGIN.value().ifPresent(builder::login); - SONAR_PASSWORD.value().ifPresent(builder::password); - SONAR_PROXY_HOST.value().ifPresent( - host -> SONAR_PROXY_PORT.value() + + Optional.ofNullable(sonarProperties.getLogin()) .ifPresent(builder::login); + + Optional.ofNullable(sonarProperties.getPassword()).ifPresent(builder::password); + Optional.ofNullable(sonarProperties.getProxyHost()).ifPresent( + host -> Optional.ofNullable(sonarProperties.getProxyPort()) .ifPresent(port -> builder.proxy(host, Integer.parseInt(port))) ); From 537d4dccb53487759db232f306f8feaaa1adb7b4 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:07:49 +0200 Subject: [PATCH 021/310] update the class GitLabProperties and remove @Validated --- .../input/external/gitlab/GitLabProperties.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java index b6017dd4d..123939897 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -1,12 +1,16 @@ package de.bonndan.nivio.input.external.gitlab; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; @ConfigurationProperties(prefix = "gitlab") -@Validated + public class GitLabProperties { + private String hostUrl; + private String personalAccessToken; + private String username; + private String password; + public String getHostUrl() { return hostUrl; } @@ -39,9 +43,4 @@ public void setPassword(String password) { this.password = password; } - private String hostUrl; - private String personalAccessToken; - private String username; - private String password; - } From 0e2918f05a0cfa37249f86b0f4f2e6ea2d7ae71a Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:10:59 +0200 Subject: [PATCH 022/310] update the method getGitLabAPI() --- .../input/external/gitlab/GitLabConfig.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java index d0342ca57..91067159d 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.input.external.gitlab; import org.gitlab4j.api.GitLabApi; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,7 +9,7 @@ import java.util.Optional; import static de.bonndan.nivio.config.ConfigurableEnvVars.*; - +import java.util.Optional; @Configuration @EnableConfigurationProperties(GitLabProperties.class) @@ -18,7 +17,6 @@ public class GitLabConfig { private final GitLabProperties gitLabProperties; - @Autowired public GitLabConfig(GitLabProperties gitLabProperties) { this.gitLabProperties = gitLabProperties; } @@ -26,22 +24,22 @@ public GitLabConfig(GitLabProperties gitLabProperties) { @Bean public GitLabApi getGitLabAPI() { - Optional hostUrl = GITLAB_HOST_URL.value(); + Optional hostUrl = Optional.ofNullable(gitLabProperties.getHostUrl()); if (hostUrl.isEmpty()) { return null; } - Optional personalAccessToken = GITLAB_PERSONAL_ACCESS_TOKEN.value(); - Optional username = GITLAB_USERNAME.value(); - Optional password = GITLAB_PASSWORD.value(); + Optional personalAccessToken = Optional.ofNullable(gitLabProperties.getPersonalAccessToken()); + Optional username = Optional.ofNullable(gitLabProperties.getUsername()); + Optional password = Optional.ofNullable(gitLabProperties.getPassword()); return getGitLabAPI(hostUrl.get(), personalAccessToken, username, password); } GitLabApi getGitLabAPI(@NonNull String hostUrl, - Optional personalAccessToken, - Optional username, - Optional password + Optional personalAccessToken, + Optional username, + Optional password ) { if (personalAccessToken.isPresent()) { From c805d1cedb1bd09d3053a86f6b9133a9d2288075 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:12:37 +0200 Subject: [PATCH 023/310] update the class GitHubProperties and remove @Validated --- .../input/external/github/GitHubProperties.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java index 2dc375645..32d380b4c 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java @@ -4,10 +4,15 @@ import org.springframework.validation.annotation.Validated; @ConfigurationProperties(prefix = "github") -@Validated + public class GitHubProperties { + private String login; + private String password; + private String oauth; + private String jwt; + public String getLogin() { return login; } @@ -40,8 +45,5 @@ public void setJwt(String jwt) { this.jwt = jwt; } - private String login; - private String password; - private String oauth; - private String jwt; + } From ac3d537b50c7d8ab83243f074cd35865646e89e7 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:16:22 +0200 Subject: [PATCH 024/310] update the method checkAnyEnv() --- .../nivio/input/external/github/GitHubConfig.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java index 0785e20b3..7ae410b20 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java @@ -28,6 +28,13 @@ public class GitHubConfig { * * export GITHUB_JWT=my_jwt_token */ + + private final GitHubProperties gitHubProperties; + + public GitHubConfig(GitHubProperties gitHubProperties) { + this.gitHubProperties = gitHubProperties; + } + @Bean public GitHub getGitHub() { @@ -45,9 +52,9 @@ public GitHub getGitHub() { } private boolean checkAnyEnv() { - return !StringUtils.isEmpty(System.getenv("GITHUB_LOGIN")) || - !StringUtils.isEmpty(System.getenv("GITHUB_PASSWORD")) || - !StringUtils.isEmpty(System.getenv("GITHUB_OAUTH")) || - !StringUtils.isEmpty(System.getenv("GITHUB_JWT")); + return !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getLogin())")) || + !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getPassword()")) || + !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getOauth()")) || + !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getJwt()")); } } From f3d8e157c72ffb35ce0679a88a42627308e9eff6 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:18:42 +0200 Subject: [PATCH 025/310] create a new application.yml file and full github with some values --- application.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/application.yml b/application.yml index e69de29bb..85b0c270b 100644 --- a/application.yml +++ b/application.yml @@ -0,0 +1,13 @@ +spring: + application: + name: nivio + main: + lazy-initialization: true + +github: # add new environment variables + login: kohsuke + password: 012345678 + oauth: 4d98173f7c075527cb64878561d1fe70 + jwt: my_jwt_token + + From acf0244e15c657ae8de1d1ee68268901f077b9e9 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 15 Jun 2021 08:22:01 +0200 Subject: [PATCH 026/310] modified the method createHandler() to avoid error messages by running the programm --- .../bonndan/nivio/input/external/LinkHandlerFactory.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java index 087d99d5d..9a346f919 100644 --- a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java +++ b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java @@ -2,6 +2,7 @@ import de.bonndan.nivio.input.external.github.GitHubRepoHandler; +import de.bonndan.nivio.input.external.gitlab.GitLabRepoHandler; import de.bonndan.nivio.input.external.openapi.OpenAPILinkHandler; import de.bonndan.nivio.input.external.sonar.SonarLinkHandler; import de.bonndan.nivio.input.external.springboot.SpringBootHealthHandler; @@ -26,6 +27,7 @@ public class LinkHandlerFactory { public static final String GITHUB = "github"; private static final String SONAR = "sonar"; private static final String SPRING_HEALTH = "spring.health"; + private static final String GITLAB = "gitlab"; // add semantics, e.g. handle identifier "sonarqube" to grab metrics // see https://github.com/dedica-team/nivio/issues/97 @@ -33,7 +35,9 @@ public class LinkHandlerFactory { GITHUB, GitHubRepoHandler.class, SONAR, SonarLinkHandler.class, SPRING_HEALTH, SpringBootHealthHandler.class, - OpenAPILinkHandler.NAMESPACE, OpenAPILinkHandler.class + OpenAPILinkHandler.NAMESPACE, OpenAPILinkHandler.class, + GITLAB, GitLabRepoHandler.class + ); private final AutowireCapableBeanFactory beanFactory; @@ -52,7 +56,7 @@ private Optional createHandler(String key, Class Date: Tue, 15 Jun 2021 09:22:32 +0200 Subject: [PATCH 027/310] update again this class --- .../de/bonndan/nivio/input/external/gitlab/GitLabConfig.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java index 91067159d..b7867674a 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabConfig.java @@ -8,9 +8,6 @@ import java.util.Optional; -import static de.bonndan.nivio.config.ConfigurableEnvVars.*; -import java.util.Optional; - @Configuration @EnableConfigurationProperties(GitLabProperties.class) public class GitLabConfig { From e0aee2ae343647658d06553f3800a777a589370e Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sun, 20 Jun 2021 09:26:34 +0200 Subject: [PATCH 028/310] [#565] relations with labels --- docs/source/schema/Models/ItemDescription.rst | 14 ++--- .../schema/Models/LandscapeDescription.rst | 4 +- docs/source/schema/spec.json | 30 +++++------ .../java/de/bonndan/nivio/input/Hint.java | 2 +- .../nivio/input/ItemDescriptionValues.java | 25 +++++++-- .../nivio/input/RelationEndpointResolver.java | 2 +- .../nivio/input/compose2/ComposeService.java | 2 +- .../input/csv/InputFormatHandlerCSV.java | 2 +- .../input/dot/InputFormatHandlerDot.java | 2 +- .../nivio/input/dto/ItemDescription.java | 7 +-- .../nivio/input/dto/RelationDescription.java | 23 +++++++- .../InputFormatHandlerKubernetes.java | 10 ++-- .../nivio/input/rancher1/APIWalker.java | 2 +- .../java/de/bonndan/nivio/model/Labeled.java | 14 ++++- .../java/de/bonndan/nivio/input/HintTest.java | 4 +- .../input/ItemDescriptionValuesTest.java | 8 +-- .../input/ItemRelationProcessorTest.java | 12 ++--- .../input/dto/RelationDescriptionTest.java | 54 +++++++++++++++++++ .../output/layout/OrganicLayouterTest.java | 9 +--- 19 files changed, 161 insertions(+), 65 deletions(-) create mode 100644 src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index fd605e2ea..1304321f8 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -78,21 +78,21 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. - optional, defaults to null - service|database|volume - * - statuses + * - frameworks + - Map + - The parts used to create the item. Usually refers to technical frameworks. + - optional, defaults to null + - java: 8 + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - frameworks - - Map - - The parts used to create the item. Usually refers to technical frameworks. - - optional, defaults to null - - java: 8 * - lifecycle - String - The lifecycle state of an item. diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..f906713fe 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,12 +63,12 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - color + * - icon - String - - optional, defaults to null - null - * - icon + * - color - String - - optional, defaults to null diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 1283fa8f0..3a468f53d 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -200,7 +200,18 @@ "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", "example" : "service|database|volume" }, - "statuses" : { + "frameworks" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "example" : "java: 8" + }, + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "writeOnly" : true, + "example" : "java: 8" + }, + "status" : { "type" : "array", "description" : "A list of statuses that works like hardcoded KPIs.", "writeOnly" : true, @@ -213,7 +224,7 @@ "description" : "A list of statuses that works like hardcoded KPIs." } }, - "status" : { + "statuses" : { "type" : "array", "description" : "A list of statuses that works like hardcoded KPIs.", "writeOnly" : true, @@ -226,17 +237,6 @@ "description" : "A list of statuses that works like hardcoded KPIs." } }, - "frameworks" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "example" : "java: 8" - }, - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "writeOnly" : true, - "example" : "java: 8" - }, "lifecycle" : { "type" : "string", "description" : "The lifecycle state of an item.", @@ -402,10 +402,10 @@ }, "description" : "Additional labels for the landscape." }, - "color" : { + "icon" : { "type" : "string" }, - "icon" : { + "color" : { "type" : "string" }, "items" : { diff --git a/src/main/java/de/bonndan/nivio/input/Hint.java b/src/main/java/de/bonndan/nivio/input/Hint.java index 7e4d7f564..b08016d6e 100644 --- a/src/main/java/de/bonndan/nivio/input/Hint.java +++ b/src/main/java/de/bonndan/nivio/input/Hint.java @@ -70,7 +70,7 @@ public void use(ItemDescription item, ItemDescription target, Optional { RelationDescription relation = createRelation(item, target); - item.addRelation(relation); + item.addOrReplaceRelation(relation); return relation; }); diff --git a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java index 70bd70b2d..3f2e54476 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java @@ -1,8 +1,12 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.input.dto.ItemDescription; +import de.bonndan.nivio.input.dto.RelationDescription; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; +import java.util.Objects; + import static de.bonndan.nivio.util.SafeAssign.assignSafe; import static de.bonndan.nivio.util.SafeAssign.assignSafeIfAbsent; @@ -27,7 +31,15 @@ public static void assignNotNull(ItemDescription existing, ItemDescription incre if (increment.getAddress() != null) existing.setAddress(increment.getAddress()); - assignSafe(increment.getRelations(), (rel) -> rel.forEach(existing::addRelation)); + increment.getRelations().forEach(relationDescription -> { + RelationDescription rel = relationDescription.findMatching(existing.getRelations()) + .map(relationDescription1 -> { + relationDescription1.merge(relationDescription); + return relationDescription1; + }) + .orElse(relationDescription); + existing.addOrReplaceRelation(rel); + }); assignSafe(increment.getInterfaces(), (set) -> set.forEach(intf -> existing.getInterfaces().add(intf))); } @@ -35,10 +47,14 @@ public static void assignNotNull(ItemDescription existing, ItemDescription incre /** * Writes the values of the template (second object) to the first where first is null. * - * @param target target + * @param target target * @param source source */ - public static void assignSafeNotNull(ItemDescription target, ItemDescription source) { + public static void assignSafeNotNull(@NonNull final ItemDescription target, @NonNull final ItemDescription source) { + + if (Objects.requireNonNull(source) == Objects.requireNonNull(target)) { + return; + } ComponentDescriptionValues.assignSafeNotNull(target, source); @@ -53,7 +69,8 @@ public static void assignSafeNotNull(ItemDescription target, ItemDescription sou .forEach(s -> target.getProvidedBy().add(s)); } - source.getRelations().forEach(target::addRelation); + + source.getRelations().forEach(target::addOrReplaceRelation); target.getInterfaces().addAll(source.getInterfaces()); } diff --git a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java index c37008e2d..4e6e8d3ab 100644 --- a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java +++ b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java @@ -38,7 +38,7 @@ private void resolveRelations(final ItemDescription description, ItemIndex { allItems.query(term).stream().findFirst().ifPresentOrElse(o -> { RelationDescription rel = RelationBuilder.createProviderDescription(o, description.getIdentifier()); - description.addRelation(rel); + description.addOrReplaceRelation(rel); }, () -> processLog.warn(description.getIdentifier() + ": no provider target found for term " + term)); }); diff --git a/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java b/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java index e535521a8..51ee2d880 100644 --- a/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java +++ b/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java @@ -49,7 +49,7 @@ public ItemDescription getDescription() { link targets become providers */ if (links != null) { - links.forEach(s -> description.addRelation(RelationBuilder.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); + links.forEach(s -> description.addOrReplaceRelation(RelationBuilder.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); } return description; diff --git a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java index cae2bf72f..cba6c4690 100644 --- a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java +++ b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java @@ -89,7 +89,7 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape if (relationDescription != null) { relationDescription.setLabels(labels); - itemDescription.addRelation(relationDescription); + itemDescription.addOrReplaceRelation(relationDescription); } else { itemDescription.getLabels().putAll(labels); } diff --git a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java index 1357e79ce..f0bab919e 100644 --- a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java +++ b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java @@ -81,7 +81,7 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape break; } }); - itemDescription.addRelation(rel); + itemDescription.addOrReplaceRelation(rel); }); items.add(itemDescription); diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index 781200619..85373ad5b 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -15,6 +15,7 @@ import javax.validation.constraints.NotEmpty; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * This is representation of a service in the textual form as described in a source file. @@ -236,11 +237,11 @@ public void setRelations(List relations) { relations.stream() .filter(s -> !StringUtils.isEmpty(s)) .map(s -> RelationBuilder.createDataflowDescription(this, s)) - .forEach(this::addRelation); + .forEach(this::addOrReplaceRelation); } - public void addRelation(RelationDescription relationItem) { - Objects.requireNonNull(relationItem); + public void addOrReplaceRelation(@NonNull final RelationDescription relationItem) { + Objects.requireNonNull(relationItem).findMatching(this.relations).ifPresent(this.relations::remove); this.relations.add(relationItem); } diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 3c0a3b94d..42a8d76b1 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -2,11 +2,11 @@ import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.search.ItemMatcher; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; -import java.util.HashMap; -import java.util.Map; +import java.util.*; @Schema(description = "A directed relation between two landscape items. Also known as edge in a directed graph.") public class RelationDescription implements Labeled { @@ -103,4 +103,23 @@ public Map getLabels() { public void setLabel(String key, String value) { getLabels().put(key, value); } + + /** + * Finds the first relation description with same source and target. + * + * @param relations a collection of existing relations + * @return the sibling + */ + public Optional findMatching(@NonNull final Collection relations) { + return Objects.requireNonNull(relations).stream() + .filter(rel -> matches(source, rel.getSource())) + .filter(rel -> matches(target, rel.getTarget())) + .findFirst(); + } + + private boolean matches(String end1, String end2) { + Optional m1 = ItemMatcher.forTarget(end1); + Optional m2 = ItemMatcher.forTarget(end2); + return m1.isPresent() && m2.isPresent() && m1.map(m -> m.equals(m2.get())).orElse(false); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index dd183ba2e..ec01cca5f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -151,7 +151,7 @@ private ItemDescription createDescriptionFromService(Service kubernetesService, //TODO, check if this is reliable if (!StringUtils.isEmpty(targetId)) { - service.addRelation(new RelationDescription(service.getIdentifier(), targetId)); + service.addOrReplaceRelation(new RelationDescription(service.getIdentifier(), targetId)); } //link pods as providers @@ -160,7 +160,7 @@ private ItemDescription createDescriptionFromService(Service kubernetesService, .forEach(pod -> { RelationDescription rel = new RelationDescription(pod.getIdentifier(), service.getIdentifier()); rel.setType(RelationType.PROVIDER); - service.addRelation(rel); + service.addOrReplaceRelation(rel); pod.setGroup(service.getGroup()); }); @@ -180,7 +180,7 @@ private List createDescriptionsFromPod(Pod pod, ItemDescription node.setIdentifier(pod.getSpec().getNodeName()); node.setType(ItemType.SERVER); descriptions.add(node); - podItem.addRelation(new RelationDescription(node.getIdentifier(), podItem.getIdentifier())); + podItem.addOrReplaceRelation(new RelationDescription(node.getIdentifier(), podItem.getIdentifier())); String group = getGroup(pod); pod.getSpec().getContainers().forEach(container -> { @@ -195,7 +195,7 @@ private List createDescriptionsFromPod(Pod pod, ItemDescription //container provides the pod RelationDescription relationDescription = new RelationDescription(containerDesc.getIdentifier(), podItem.getIdentifier()); relationDescription.setType(RelationType.PROVIDER); - containerDesc.addRelation(relationDescription); + containerDesc.addOrReplaceRelation(relationDescription); // TODO //description.setScale(...); @@ -240,7 +240,7 @@ private ItemDescription createVolumeDescription(String group, Volume volume, Pod //volume provides the pod RelationDescription relationDescription = new RelationDescription(volumeDesc.getIdentifier(), podItem.getIdentifier()); relationDescription.setType(RelationType.PROVIDER); - volumeDesc.addRelation(relationDescription); + volumeDesc.addOrReplaceRelation(relationDescription); return volumeDesc; } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java b/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java index 8e60ec2b2..73a53a9d4 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java @@ -147,7 +147,7 @@ private List asDescriptions(List data, final Map> indexedByPrefix(String prefix) { * @param source label source * @param target target */ - static void merge(Labeled source, Labeled target) { + static void merge(@NonNull final Labeled source, @NonNull final Labeled target) { source.getLabels().entrySet().stream() .filter(entry -> entry.getValue() != null) .filter(entry -> target.getLabel(entry.getKey()) == null) .forEach(entry -> target.setLabel(entry.getKey(), entry.getValue())); } + /** + * Copies all non-null labels from source. + * + * @param source label source + */ + default void merge(@NonNull final Labeled source) { + Objects.requireNonNull(source).getLabels().entrySet().stream() + .filter(entry -> entry.getValue() != null) + .filter(entry -> getLabel(entry.getKey()) == null) + .forEach(entry -> setLabel(entry.getKey(), entry.getValue())); + } + /** * Compares the labels against a previous version. * diff --git a/src/test/java/de/bonndan/nivio/input/HintTest.java b/src/test/java/de/bonndan/nivio/input/HintTest.java index 2d0ca64ef..b0b0d7472 100644 --- a/src/test/java/de/bonndan/nivio/input/HintTest.java +++ b/src/test/java/de/bonndan/nivio/input/HintTest.java @@ -100,7 +100,7 @@ void doesNotOverwriteExistingRelation() { RelationDescription relation = new RelationDescription(source.getIdentifier(), target.getIdentifier()); relation.setType(RelationType.DATAFLOW); - source.addRelation(relation); + source.addOrReplaceRelation(relation); //when hint.use(source, target, Optional.of(relation)); @@ -118,7 +118,7 @@ void setsTypeOnExistingRelation() { Hint hint = new Hint(ItemType.DATABASE, RelationType.PROVIDER, null); RelationDescription relation = new RelationDescription(source.getIdentifier(), target.getIdentifier()); - source.addRelation(relation); + source.addOrReplaceRelation(relation); //when hint.use(source, target, Optional.of(relation)); diff --git a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java index ab785d05b..bfbec4808 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java @@ -80,12 +80,12 @@ public void incrementAddsDataflow() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); RelationDescription other = RelationBuilder.createDataflowDescription(sd1, "other"); - sd1.addRelation(other); + sd1.addOrReplaceRelation(other); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); RelationDescription another = RelationBuilder.createDataflowDescription(increment, "another"); - increment.addRelation(another); + increment.addOrReplaceRelation(another); ItemDescriptionValues.assignNotNull(sd1, increment); @@ -114,13 +114,13 @@ public void incrementAddsProvidedBy() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); RelationDescription dbProvider = RelationBuilder.createProviderDescription(sd1, "db1"); - sd1.addRelation(dbProvider); + sd1.addOrReplaceRelation(dbProvider); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); RelationDescription redisProvider = RelationBuilder.createProviderDescription(sd1, "redis"); - increment.addRelation(redisProvider); + increment.addOrReplaceRelation(redisProvider); ItemDescriptionValues.assignNotNull(sd1, increment); diff --git a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java index 9f68bef82..591ac8509 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java @@ -48,13 +48,13 @@ void processAddsRelation() { ItemDescription description = new ItemDescription("foo"); description.setGroup("a"); - description.addRelation(new RelationDescription("foo", "bar")); - description.addRelation(new RelationDescription("foo", "baz")); + description.addOrReplaceRelation(new RelationDescription("foo", "bar")); + description.addOrReplaceRelation(new RelationDescription("foo", "baz")); input.mergeItems(List.of(description)); //new ItemDescription bar = new ItemDescription("bar"); bar.setGroup("a"); - bar.addRelation(new RelationDescription("bar", "baz")); + bar.addOrReplaceRelation(new RelationDescription("bar", "baz")); input.mergeItems(List.of(bar)); //when @@ -72,8 +72,8 @@ void processAddsUpdates() { description.setGroup("a"); RelationDescription relationItem = new RelationDescription("foo", "bar"); relationItem.setFormat("JSON"); - description.addRelation(relationItem); - description.addRelation(new RelationDescription("foo", "baz")); + description.addOrReplaceRelation(relationItem); + description.addOrReplaceRelation(new RelationDescription("foo", "baz")); input.mergeItems(List.of(description)); //when @@ -88,7 +88,7 @@ void processRemovesRelation() { ItemDescription description = new ItemDescription("foo"); description.setGroup("a"); - description.addRelation(new RelationDescription("foo", "bar")); + description.addOrReplaceRelation(new RelationDescription("foo", "bar")); input.mergeItems(List.of(description)); //when diff --git a/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java new file mode 100644 index 000000000..286f5fc8b --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java @@ -0,0 +1,54 @@ +package de.bonndan.nivio.input.dto; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class RelationDescriptionTest { + + private List relations; + + @BeforeEach + void setup() { + relations = List.of(new RelationDescription("agroup/foo", "bgroup/bar")); + } + + @Test + void findMatching() { + var rel = new RelationDescription("aGroup/foo", "bGroup/Bar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isPresent(); + } + + @Test + void findMatchingOtherSource() { + var rel = new RelationDescription("aGroup/notfoo", "bGroup/Bar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isEmpty(); + } + + @Test + void findMatchingOtherTarget() { + var rel = new RelationDescription("aGroup/foo", "bGroup/notBar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isEmpty(); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java b/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java index a6904e0ee..2dfaed596 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.output.layout; import com.fasterxml.jackson.databind.ObjectMapper; -import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.Indexer; import de.bonndan.nivio.input.InputFormatHandlerFactory; @@ -12,16 +11,11 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.http.HttpService; -import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.output.RenderingTest; import de.bonndan.nivio.output.icons.IconService; import de.bonndan.nivio.output.icons.LocalIcons; import de.bonndan.nivio.output.icons.ExternalIcons; -import de.bonndan.nivio.output.map.svg.MapStyleSheetFactory; -import de.bonndan.nivio.output.map.svg.SVGDocument; -import de.bonndan.nivio.output.map.svg.SVGRenderer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationEventPublisher; @@ -36,7 +30,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; class OrganicLayouterTest extends RenderingTest { @@ -135,7 +128,7 @@ public void debugRenderLargeGraphSVG() throws IOException { for (int i = 0; i < 20; i++) { var source = descriptionList.get(i); var target = descriptionList.get(i + 20); - source.addRelation(new RelationDescription(source.getIdentifier(), target.getIdentifier())); + source.addOrReplaceRelation(new RelationDescription(source.getIdentifier(), target.getIdentifier())); } indexer.index(input); From a76a37d5dbf86c2c2f8220427487b34cbfdb7d19 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 08:36:31 +0200 Subject: [PATCH 029/310] [#565] relations with labels --- .../nivio/input/ItemDescriptionValues.java | 1 - .../nivio/input/ItemRelationProcessor.java | 8 ++--- .../nivio/input/RelationEndpointResolver.java | 4 +-- .../nivio/input/compose2/ComposeService.java | 4 +-- .../nivio/input/dto/ItemDescription.java | 10 ++++-- .../java/de/bonndan/nivio/model/Relation.java | 6 ---- ...ationBuilder.java => RelationFactory.java} | 13 ++++++- .../input/ItemDescriptionValuesTest.java | 10 +++--- .../input/ItemRelationProcessorTest.java | 8 ++--- .../nivio/input/ProcessingChangelogTest.java | 3 +- .../java/de/bonndan/nivio/model/ItemTest.java | 4 +-- ...lderTest.java => RelationFactoryTest.java} | 34 +++++++++---------- .../de/bonndan/nivio/model/RelationTest.java | 4 +-- .../output/layout/AllGroupsLayoutTest.java | 6 ++-- .../nivio/output/layout/SubLayoutTest.java | 10 +++--- .../map/svg/SVGDimensionFactoryTest.java | 3 +- .../nivio/output/map/svg/SVGRelationTest.java | 2 +- 17 files changed, 70 insertions(+), 60 deletions(-) rename src/main/java/de/bonndan/nivio/model/{RelationBuilder.java => RelationFactory.java} (92%) rename src/test/java/de/bonndan/nivio/model/{RelationBuilderTest.java => RelationFactoryTest.java} (76%) diff --git a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java index 3f2e54476..c6df223a2 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java @@ -69,7 +69,6 @@ public static void assignSafeNotNull(@NonNull final ItemDescription target, @Non .forEach(s -> target.getProvidedBy().add(s)); } - source.getRelations().forEach(target::addOrReplaceRelation); target.getInterfaces().addAll(source.getInterfaces()); diff --git a/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java b/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java index 16fedba19..45df329fc 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java +++ b/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java @@ -35,7 +35,7 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N Relation current = getCurrentRelation(relationDescription, landscape, origin) .map(relation -> { - Relation update = RelationBuilder.update(relation, relationDescription, landscape); + Relation update = RelationFactory.update(relation, relationDescription, landscape); List changes = relation.getChanges(update); if (!changes.isEmpty()) { processLog.info(String.format(origin + ": Updating relation between %s and %s", update.getSource(), update.getTarget())); @@ -44,7 +44,7 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N return update; }) .orElseGet(() -> { - Relation created = RelationBuilder.create(origin, relationDescription, landscape); + Relation created = RelationFactory.create(origin, relationDescription, landscape); processLog.info(String.format(origin + ": Adding relation between %s and %s", created.getSource(), created.getTarget())); changelog.addEntry(created, ProcessingChangelog.ChangeType.CREATED, null); return created; @@ -123,11 +123,11 @@ private Optional getCurrentRelation(RelationDescription relationDescri Item target = landscape.findOneBy(relationDescription.getTarget(), origin.getGroup()); Iterator iterator = origin.getRelations().iterator(); - Relation created = new Relation(source, target); + Relation virtual = RelationFactory.createForTesting(source, target); Relation existing; while (iterator.hasNext()) { existing = iterator.next(); - if (existing.equals(created)) { + if (existing.equals(virtual)) { return Optional.of(existing); } } diff --git a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java index 4e6e8d3ab..c09da2c73 100644 --- a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java +++ b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java @@ -4,7 +4,7 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.search.ItemIndex; -import de.bonndan.nivio.model.RelationBuilder; +import de.bonndan.nivio.model.RelationFactory; import org.springframework.util.StringUtils; import java.util.Collection; @@ -37,7 +37,7 @@ private void resolveRelations(final ItemDescription description, ItemIndex { allItems.query(term).stream().findFirst().ifPresentOrElse(o -> { - RelationDescription rel = RelationBuilder.createProviderDescription(o, description.getIdentifier()); + RelationDescription rel = RelationFactory.createProviderDescription(o, description.getIdentifier()); description.addOrReplaceRelation(rel); }, () -> processLog.warn(description.getIdentifier() + ": no provider target found for term " + term)); diff --git a/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java b/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java index 51ee2d880..8c46ee14b 100644 --- a/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java +++ b/src/main/java/de/bonndan/nivio/input/compose2/ComposeService.java @@ -3,7 +3,7 @@ import de.bonndan.nivio.input.dto.InterfaceDescription; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.model.Label; -import de.bonndan.nivio.model.RelationBuilder; +import de.bonndan.nivio.model.RelationFactory; import java.util.HashSet; import java.util.List; @@ -49,7 +49,7 @@ public ItemDescription getDescription() { link targets become providers */ if (links != null) { - links.forEach(s -> description.addOrReplaceRelation(RelationBuilder.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); + links.forEach(s -> description.addOrReplaceRelation(RelationFactory.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); } return description; diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index 85373ad5b..aed35edb9 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -15,7 +15,6 @@ import javax.validation.constraints.NotEmpty; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; /** * This is representation of a service in the textual form as described in a source file. @@ -236,10 +235,17 @@ public Set getRelations() { public void setRelations(List relations) { relations.stream() .filter(s -> !StringUtils.isEmpty(s)) - .map(s -> RelationBuilder.createDataflowDescription(this, s)) + .map(s -> RelationFactory.createDataflowDescription(this, s)) .forEach(this::addOrReplaceRelation); } + /** + * Add or update a relation description. + * + * If an equal relation description exist, it is replaced by the newer one. + * + * @param relationItem relation dto to be added + */ public void addOrReplaceRelation(@NonNull final RelationDescription relationItem) { Objects.requireNonNull(relationItem).findMatching(this.relations).ifPresent(this.relations::remove); this.relations.add(relationItem); diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 38548c1dc..2064630c1 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -36,12 +36,6 @@ public class Relation implements Labeled, Serializable { private final Map labels = new HashMap<>(); - public Relation(@NonNull final Item source, - @NonNull final Item target - ) { - this(source, target, null, null, null); - } - public Relation(@NonNull final Item source, @NonNull final Item target, final String description, diff --git a/src/main/java/de/bonndan/nivio/model/RelationBuilder.java b/src/main/java/de/bonndan/nivio/model/RelationFactory.java similarity index 92% rename from src/main/java/de/bonndan/nivio/model/RelationBuilder.java rename to src/main/java/de/bonndan/nivio/model/RelationFactory.java index 660494cc7..7d69004c1 100644 --- a/src/main/java/de/bonndan/nivio/model/RelationBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/RelationFactory.java @@ -6,7 +6,12 @@ import java.util.Objects; -public class RelationBuilder { +/** + * Factory to create {@link Relation} instances. + * + * + */ +public class RelationFactory { public static RelationDescription createProviderDescription(ItemDescription source, String target) { return createProviderDescription(source.getIdentifier(), target); @@ -102,4 +107,10 @@ public static Relation create(@NonNull final Item origin, ); } + /** + * Creates a relation instance without any checks. + */ + public static Relation createForTesting(Item source, Item target) { + return new Relation(source, target, null, null, null); + } } diff --git a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java index bfbec4808..54133fe49 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java @@ -5,7 +5,7 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; -import de.bonndan.nivio.model.RelationBuilder; +import de.bonndan.nivio.model.RelationFactory; import de.bonndan.nivio.model.RelationType; import org.junit.jupiter.api.Test; @@ -79,12 +79,12 @@ public void incrementAddsDataflow() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); - RelationDescription other = RelationBuilder.createDataflowDescription(sd1, "other"); + RelationDescription other = RelationFactory.createDataflowDescription(sd1, "other"); sd1.addOrReplaceRelation(other); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); - RelationDescription another = RelationBuilder.createDataflowDescription(increment, "another"); + RelationDescription another = RelationFactory.createDataflowDescription(increment, "another"); increment.addOrReplaceRelation(another); ItemDescriptionValues.assignNotNull(sd1, increment); @@ -113,13 +113,13 @@ public void incrementAddsProvidedBy() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); - RelationDescription dbProvider = RelationBuilder.createProviderDescription(sd1, "db1"); + RelationDescription dbProvider = RelationFactory.createProviderDescription(sd1, "db1"); sd1.addOrReplaceRelation(dbProvider); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); - RelationDescription redisProvider = RelationBuilder.createProviderDescription(sd1, "redis"); + RelationDescription redisProvider = RelationFactory.createProviderDescription(sd1, "redis"); increment.addOrReplaceRelation(redisProvider); ItemDescriptionValues.assignNotNull(sd1, increment); diff --git a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java index 591ac8509..228a93235 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java @@ -32,11 +32,11 @@ void setUp() { Item baz = ItemFactory.getTestItem("a", "baz"); items.add(baz); - foo.addOrReplace(new Relation(foo, bar)); - bar.addOrReplace(new Relation(foo, bar)); + foo.addOrReplace(RelationFactory.createForTesting(foo, bar)); + bar.addOrReplace(RelationFactory.createForTesting(foo, bar)); - foo.addOrReplace(new Relation(foo, baz)); - baz.addOrReplace(new Relation(foo, baz)); + foo.addOrReplace(RelationFactory.createForTesting(foo, baz)); + baz.addOrReplace(RelationFactory.createForTesting(foo, baz)); landscape = LandscapeFactory.createForTesting("test", "test").withItems(items).build(); diff --git a/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java b/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java index bcfa27a7e..8cf8b2a04 100644 --- a/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java +++ b/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java @@ -3,6 +3,7 @@ import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.ItemFactory; import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.RelationFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -59,7 +60,7 @@ void testAddEntryWithoutMessage() { void addRelation() { //when Item bar = ItemFactory.getTestItem("foo", "bar"); - Relation relation = new Relation(this.testItem, bar); + Relation relation = RelationFactory.createForTesting(this.testItem, bar); changelog.addEntry(relation, ProcessingChangelog.ChangeType.DELETED, null); //then diff --git a/src/test/java/de/bonndan/nivio/model/ItemTest.java b/src/test/java/de/bonndan/nivio/model/ItemTest.java index df9d5550b..faf3ca5f5 100644 --- a/src/test/java/de/bonndan/nivio/model/ItemTest.java +++ b/src/test/java/de/bonndan/nivio/model/ItemTest.java @@ -151,11 +151,11 @@ public void setRelations() { Item s2 = getTestItemBuilder("g1", "b").build(); Item s3 = getTestItemBuilder("g1", "c").build(); - s1.setRelations(Set.of(new Relation(s1, s2))); + s1.setRelations(Set.of(RelationFactory.createForTesting(s1, s2))); assertThat(s1.getRelations()).hasSize(1); //when - s1.setRelations(Set.of(new Relation(s1, s3))); + s1.setRelations(Set.of(RelationFactory.createForTesting(s1, s3))); assertThat(s1.getRelations()).hasSize(1); } } diff --git a/src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java similarity index 76% rename from src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java rename to src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java index 6083f7248..1bd37f96c 100644 --- a/src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java +++ b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java @@ -11,7 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -class RelationBuilderTest { +class RelationFactoryTest { private Landscape landscape; @@ -23,7 +23,7 @@ void setUp() { @Test void createProviderDescription() { //when - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); //then assertThat(providerDescription).isNotNull(); @@ -38,7 +38,7 @@ void createDataflowDescription() { ItemDescription desc = new ItemDescription("foo"); //when - RelationDescription providerDescription = RelationBuilder.createDataflowDescription(desc, "bar"); + RelationDescription providerDescription = RelationFactory.createDataflowDescription(desc, "bar"); //then assertThat(providerDescription).isNotNull(); @@ -55,7 +55,7 @@ void createProviderRelation() { Item bar = ItemFactory.getTestItem("b", "bar"); //when - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); //then assertThat(relation).isNotNull(); @@ -70,17 +70,17 @@ void update() { //given Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(foo, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); providerDescription.setFormat("json"); providerDescription.setDescription("huhu"); //when - Relation newRelation = RelationBuilder.update(relation, providerDescription, landscape); + Relation newRelation = RelationFactory.update(relation, providerDescription, landscape); //then assertThat(newRelation.getSource()).isEqualTo(foo); @@ -95,15 +95,15 @@ void updateThrows() { //given Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(foo, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "oops"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "oops"); //when - assertThrows(NoSuchElementException.class, () -> RelationBuilder.update(relation, providerDescription, landscape)); + assertThrows(NoSuchElementException.class, () -> RelationFactory.update(relation, providerDescription, landscape)); } @Test @@ -113,15 +113,15 @@ void updateRegardsReference() { Item foo = ItemFactory.getTestItem("a", "foo"); Item fooCopy = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(fooCopy, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); //when - Relation newRelation = RelationBuilder.update(relation, providerDescription, landscape); + Relation newRelation = RelationFactory.update(relation, providerDescription, landscape); //then assertThat(newRelation.getSource() == fooCopy).isTrue(); //ensuring the item in the landscape is used @@ -135,10 +135,10 @@ void create() { Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); landscape.setItems(Set.of(foo, bar)); - RelationDescription relationDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription relationDescription = RelationFactory.createProviderDescription("foo", "bar"); //when - Relation newRelation = RelationBuilder.create(foo, relationDescription, landscape); + Relation newRelation = RelationFactory.create(foo, relationDescription, landscape); //then assertThat(newRelation.getSource()).isEqualTo(foo); @@ -152,9 +152,9 @@ void createThrows() { Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); landscape.setItems(Set.of(foo, bar)); - RelationDescription relationDescription = RelationBuilder.createProviderDescription("foo", "oops"); + RelationDescription relationDescription = RelationFactory.createProviderDescription("foo", "oops"); //when - assertThrows(NoSuchElementException.class, () -> RelationBuilder.create(foo, relationDescription, landscape)); + assertThrows(NoSuchElementException.class, () -> RelationFactory.create(foo, relationDescription, landscape)); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/RelationTest.java b/src/test/java/de/bonndan/nivio/model/RelationTest.java index f98d90672..e1f7413bb 100644 --- a/src/test/java/de/bonndan/nivio/model/RelationTest.java +++ b/src/test/java/de/bonndan/nivio/model/RelationTest.java @@ -32,7 +32,7 @@ void toApiModel() { void inbound() { Item one = getTestItem("foo", "bar"); Item two = getTestItem("foo", "baz"); - Relation relation = new Relation(one, two); + Relation relation = RelationFactory.createForTesting(one, two); Relation.ApiModel apiModel = new Relation.ApiModel(relation, two); @@ -45,7 +45,7 @@ void inbound() { void inboundName() { Item one = getTestItemBuilder("foo", "bar").withName("huhu").build(); Item two = getTestItem("foo", "baz"); - Relation relation = new Relation(one, two); + Relation relation = RelationFactory.createForTesting(one, two); Relation.ApiModel apiModel = new Relation.ApiModel(relation, two); diff --git a/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java b/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java index de770b73a..52ff9b2a9 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java @@ -36,8 +36,8 @@ public void testWithARelation() { Item item1 = a.getItems().iterator().next(); Item item2 = b.getItems().iterator().next(); Item item3 = c.getItems().iterator().next(); - item1.addOrReplace(new Relation(item1, item2)); - item2.addOrReplace(new Relation(item2, item3)); + item1.addOrReplace(RelationFactory.createForTesting(item1, item2)); + item2.addOrReplace(RelationFactory.createForTesting(item2, item3)); Map groupMap = new LinkedHashMap<>(); landscape.getGroups().forEach(groupMap::put); @@ -64,7 +64,7 @@ private SubLayout getSubLayout(Group group) { Item baz = getTestItem(group.getIdentifier(), "baz" + group.getIdentifier()); group.addItem(baz); - baz.addOrReplace(new Relation(baz, bar)); + baz.addOrReplace(RelationFactory.createForTesting(baz, bar)); return new SubLayout(group, Set.of(bar, baz), new LandscapeConfig.LayoutConfig()); } diff --git a/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java b/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java index ac6502bd2..9579217f2 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java @@ -1,9 +1,6 @@ package de.bonndan.nivio.output.layout; -import de.bonndan.nivio.model.LandscapeConfig; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.*; import org.junit.jupiter.api.Test; import java.util.HashSet; @@ -20,12 +17,13 @@ public void testWithARelation() { //given Group foo = new Group("foo", "landscapeIdentifier"); - Item bar = getTestItem(foo.getIdentifier(), "bar");; + Item bar = getTestItem(foo.getIdentifier(), "bar"); + ; foo.addItem(bar); Item baz = getTestItem(foo.getIdentifier(), "baz"); foo.addItem(baz); - baz.addOrReplace(new Relation(baz, bar)); + baz.addOrReplace(RelationFactory.createForTesting(baz, bar)); HashSet objects = new HashSet<>(); objects.add(bar); diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java index 85e50ee50..6052f669d 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java @@ -5,6 +5,7 @@ import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.ItemFactory; import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.RelationFactory; import de.bonndan.nivio.output.map.hex.Hex; import org.junit.jupiter.api.Test; @@ -57,7 +58,7 @@ void boundingBoxesWithRelations() { //when Hex three = new Hex(-10, -10); - SVGRelation svgRelation = new SVGRelation(new HexPath(List.of(three)), "aaccee", new Relation(ItemFactory.getTestItem("foo", "bar"), ItemFactory.getTestItem("foo", "baz")), null); + SVGRelation svgRelation = new SVGRelation(new HexPath(List.of(three)), "aaccee", RelationFactory.createForTesting(ItemFactory.getTestItem("foo", "bar"), ItemFactory.getTestItem("foo", "baz")), null); SVGDimension dimension = SVGDimensionFactory.getDimension(List.of(svgGroupArea), List.of(svgRelation)); //then diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java index 55f155d19..3d3b3c31e 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java @@ -38,7 +38,7 @@ void setup() { @DisplayName("items without groups use proper fqi") public void relationContainsBothEnds() { - Relation itemRelationItem = new Relation(foo, bar); + Relation itemRelationItem = RelationFactory.createForTesting(foo, bar); SVGRelation svgRelation = new SVGRelation(hexpath, "aabbee", itemRelationItem, statusValue); DomContent render = svgRelation.render(); String render1 = render.render(); From d1a6553992c99fbbc503eb7dadf413ff416cf021 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 13:18:20 +0200 Subject: [PATCH 030/310] [#565] relations assessable --- .../bonndan/nivio/assessment/Assessable.java | 19 +++-- .../bonndan/nivio/assessment/Assessment.java | 6 +- .../nivio/assessment/AssessmentFactory.java | 25 +++--- .../nivio/assessment/kpi/AbstractKPI.java | 13 ++-- .../nivio/assessment/kpi/ConditionKPI.java | 10 ++- .../de/bonndan/nivio/assessment/kpi/KPI.java | 10 ++- .../nivio/assessment/kpi/ScalingKPI.java | 4 +- .../java/de/bonndan/nivio/model/Group.java | 9 ++- .../java/de/bonndan/nivio/model/Item.java | 5 ++ .../de/bonndan/nivio/model/Landscape.java | 5 ++ .../java/de/bonndan/nivio/model/Relation.java | 16 +++- .../nivio/output/map/svg/SVGDocument.java | 6 +- .../de/bonndan/nivio/search/SearchIndex.java | 4 +- .../nivio/assessment/AssessableTest.java | 76 +++++-------------- .../assessment/AssessmentFactoryTest.java | 14 ++-- .../assessment/AssessmentRepositoryTest.java | 4 +- 16 files changed, 115 insertions(+), 111 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessable.java b/src/main/java/de/bonndan/nivio/assessment/Assessable.java index a06594da0..6880bb460 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessable.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessable.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.FullyQualifiedIdentifier; import org.springframework.lang.NonNull; @@ -14,7 +13,7 @@ /** * Interface for components that can be assessed and can have assigned {@link StatusValue}s. */ -public interface Assessable extends Component { +public interface Assessable { /** * Returns pre-set status values not computed by {@link KPI}s. @@ -26,6 +25,14 @@ public interface Assessable extends Component { @JsonIgnore Set getAdditionalStatusValues(); + /** + * Returns the string to be used as key/identifier for a component assessment. + * + * @return map key / identifier + */ + @JsonIgnore + String getAssessmentIdentifier(); + /** * Returns the components to be assessed before this (e.g. group items). */ @@ -40,8 +47,8 @@ default List getChildren() { * @param kpis kpis used for assessment * @return a map with statusValues indexed by {@link FullyQualifiedIdentifier} */ - default Map> applyKPIs(final Map kpis) { - final Map> map = new HashMap<>(); + default Map> applyKPIs(final Map kpis) { + final Map> map = new HashMap<>(); List childrenValues = new ArrayList<>(); //apply to children @@ -51,7 +58,7 @@ default Map> applyKPIs(final Map()); //add preset status values @@ -71,7 +78,7 @@ default Map> applyKPIs(final Map> results; + private final Map> results; private final LocalDateTime date; - public Assessment(Map> results) { + public Assessment(Map> results) { date = LocalDateTime.now(); this.results = results; } - public Map> getResults() { + public Map> getResults() { return results; } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java index e25752ee7..296ad7f3b 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; import de.bonndan.nivio.model.Landscape; import org.springframework.lang.NonNull; @@ -11,7 +10,8 @@ import java.util.Objects; public class AssessmentFactory { - public static final String ASSESSMENTERRORNULL = "Assessments can't be created from a null value"; + + static final String ASSESSMENT_ERROR_NULL = "Assessments can't be created from a null value"; private AssessmentFactory() { } @@ -24,23 +24,24 @@ private AssessmentFactory() { * @throws NullPointerException On null input. */ public static Assessment createAssessment(@NonNull Landscape landscape) { - var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENTERRORNULL); + var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENT_ERROR_NULL); return new Assessment(testedLandscape.applyKPIs(testedLandscape.getKpis())); } /** - * This method which generates a new from a landscape and a kpi. + * This method which generates a new assessment from a landscape and a kpi. * * @param landscape used to generate the new Assessment. * @param kpis external kpi used to get status values. * @return Assessment * @throws NullPointerException On null input. */ - public static Assessment createAssessment(@NonNull Landscape landscape, @NonNull Map kpis) { - var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENTERRORNULL); - var testedKpis = Objects.requireNonNull(kpis, ASSESSMENTERRORNULL); - var map = new HashMap>(); - testedKpis.forEach((k, v) -> map.putIfAbsent(FullyQualifiedIdentifier.from(k), v.getStatusValues(testedLandscape))); + @NonNull + public static Assessment createAssessment(@NonNull final Landscape landscape, @NonNull Map kpis) { + var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENT_ERROR_NULL); + var testedKpis = Objects.requireNonNull(kpis, ASSESSMENT_ERROR_NULL); + var map = new HashMap>(); + testedKpis.forEach((k, v) -> map.putIfAbsent(k, v.getStatusValues(testedLandscape))); return new Assessment(map); } @@ -51,9 +52,9 @@ public static Assessment createAssessment(@NonNull Landscape landscape, @NonNull * @return Assessment * @throws NullPointerException On null input. */ - public static Assessment createAssessment(@NonNull Map> results) { - var testedResult = Objects.requireNonNull(results, ASSESSMENTERRORNULL); - return new Assessment(testedResult); + @NonNull + public static Assessment createAssessment(@NonNull Map> results) { + return new Assessment(Objects.requireNonNull(results, ASSESSMENT_ERROR_NULL)); } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java index 0b58a3ef6..eb688910d 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Component; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -13,8 +13,9 @@ */ public abstract class AbstractKPI implements KPI { - protected Function valueFunction; - protected Function msgFunction; + protected Function valueFunction; + protected Function msgFunction; + private String description; private boolean enabled = true; @@ -26,8 +27,8 @@ public AbstractKPI() { * @param valueFunction the label which is evaluated for status * @param msgFunction the label which is used as optional message */ - public AbstractKPI(@NonNull Function valueFunction, - @Nullable Function msgFunction + public AbstractKPI(@NonNull Function valueFunction, + @Nullable Function msgFunction ) { this.valueFunction = valueFunction; this.msgFunction = msgFunction; @@ -40,7 +41,7 @@ public AbstractKPI(@NonNull Function valueFunction, * @return current status value, unknown if not present */ @NonNull - public List getStatusValues(Component component) { + public List getStatusValues(Assessable component) { if (valueFunction == null) { throw new RuntimeException("Value function not initialized "); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java index bf8904776..6d79611aa 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java @@ -1,11 +1,12 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -25,7 +26,8 @@ public class ConditionKPI implements KPI { private boolean enabled = true; @Override - public List getStatusValues(Component component) { + @NonNull + public List getStatusValues(Assessable component) { if (!(component instanceof Labeled)) return new ArrayList<>(); @@ -36,12 +38,12 @@ public List getStatusValues(Component component) { String flag = entry.getValue(); if (StringUtils.isEmpty(flag)) continue; - if (flag.toLowerCase().equals("false")) { + if (flag.equalsIgnoreCase("false")) { status = Status.RED; message = key; } - if (flag.toLowerCase().equals("true") && !status.equals(Status.RED)) { + if (flag.equalsIgnoreCase("true") && !status.equals(Status.RED)) { status = Status.GREEN; message = key; } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java index 9fee4a023..4e6a90229 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Component; @@ -18,19 +19,20 @@ public interface KPI { /** * Controlled initialisation. * - * @throws ProcessingException if initialisation fails (eg regex compiling) * @param kpiConfig optional config + * @throws ProcessingException if initialisation fails (eg regex compiling) */ - default void init(@Nullable KPIConfig kpiConfig) {} + default void init(@Nullable KPIConfig kpiConfig) { + } /** * Returns the status evaluation of the component on the configured field. * - * @param component to assess + * @param assessable to assess * @return current status value, unknown if not present */ @NonNull - List getStatusValues(Component component); + List getStatusValues(Assessable assessable); /** * Describes the meaning of the KPI. diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java index 4356b2a8e..54465b4ec 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java @@ -1,8 +1,8 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.RelationType; @@ -32,7 +32,7 @@ public class ScalingKPI extends AbstractKPI { @NonNull @Override - public List getStatusValues(Component component) { + public List getStatusValues(Assessable component) { if (!(component instanceof Item)) { return Collections.emptyList(); diff --git a/src/main/java/de/bonndan/nivio/model/Group.java b/src/main/java/de/bonndan/nivio/model/Group.java index 77494fdb6..44777d7a7 100644 --- a/src/main/java/de/bonndan/nivio/model/Group.java +++ b/src/main/java/de/bonndan/nivio/model/Group.java @@ -20,7 +20,7 @@ * * Each item can only be member of one group. */ -public class Group implements Labeled, Linked, Assessable { +public class Group implements Component, Labeled, Linked, Assessable { /** * Default group identifier (items are assigned to this group if no group is given @@ -180,6 +180,11 @@ public Set getAdditionalStatusValues() { return StatusValue.fromMapping(indexedByPrefix(Label.status)); } + @Override + public String getAssessmentIdentifier() { + return getFullyQualifiedIdentifier().toString(); + } + @JsonIgnore @Override @NonNull @@ -206,7 +211,7 @@ public String toString() { * @throws IllegalArgumentException if the item group field mismatches */ public void addItem(Item item) { - if (!item.getGroup().equals(identifier)) { + if (!identifier.equals(item.getGroup())) { throw new IllegalArgumentException(String.format("Item group '%s' cannot be added to group '%s'", item.getGroup(), identifier)); } diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index abdb1c954..7b0cd62c2 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -301,6 +301,11 @@ public Set getAdditionalStatusValues() { return StatusValue.fromMapping(indexedByPrefix(Label.status)); } + @Override + public String getAssessmentIdentifier() { + return getFullyQualifiedIdentifier().toString(); + } + /** * Compare on field level against a newer version. diff --git a/src/main/java/de/bonndan/nivio/model/Landscape.java b/src/main/java/de/bonndan/nivio/model/Landscape.java index 20238e2b4..826f06b64 100644 --- a/src/main/java/de/bonndan/nivio/model/Landscape.java +++ b/src/main/java/de/bonndan/nivio/model/Landscape.java @@ -253,6 +253,11 @@ public Set getAdditionalStatusValues() { return StatusValue.fromMapping(indexedByPrefix(Label.status)); } + @Override + public String getAssessmentIdentifier() { + return getFullyQualifiedIdentifier().toString(); + } + @Override public List getChildren() { return getGroups().values().stream().map(groupItem -> (Assessable) groupItem).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 2064630c1..10e03e2e3 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonInclude; +import de.bonndan.nivio.assessment.Assessable; +import de.bonndan.nivio.assessment.StatusValue; import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; @@ -18,7 +20,7 @@ * Outgoing flows having a target which matches a service identifier will cause a relation to be created. */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class Relation implements Labeled, Serializable { +public class Relation implements Labeled, Assessable, Serializable { public static final String DELIMITER = ";"; @@ -113,6 +115,16 @@ public void setLabel(String key, String value) { labels.put(key, value); } + @Override + public Set getAdditionalStatusValues() { + return StatusValue.fromMapping(indexedByPrefix(Label.status)); + } + + @Override + public String getAssessmentIdentifier() { + return getIdentifier(); + } + @JsonInclude(JsonInclude.Include.NON_NULL) static class ApiModel { @@ -163,7 +175,7 @@ static class ApiModel { * @throws IllegalArgumentException if the arg is not comparable */ public List getChanges(Relation newer) { - if (!newer.equals(this)) { + if (!this.equals(newer)) { throw new IllegalArgumentException(String.format("Cannot compare relation %s against %s", newer, this)); } diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java index c379a6d0d..2e89cff9d 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java @@ -82,7 +82,7 @@ public DomContent render() { SVGItemLabel label = new SVGItemLabel(item); Point2D.Double pos = hexMap.hexForItem(item).toPixel(); - List itemStatuses = assessment.getResults().get(item.getFullyQualifiedIdentifier()); + List itemStatuses = assessment.getResults().get(item.getFullyQualifiedIdentifier().toString()); SVGItem SVGItem = new SVGItem(label.render(), layoutedItem, itemStatuses, pos); items.add(SVGItem.render()); }); @@ -92,7 +92,7 @@ public DomContent render() { List groups = layouted.getChildren().stream().map(groupLayout -> { Group group = (Group) groupLayout.getComponent(); Set groupArea = hexMap.getGroupArea(group); - List groupStatuses = assessment.getResults().get(group.getFullyQualifiedIdentifier()); + List groupStatuses = assessment.getResults().get(group.getFullyQualifiedIdentifier().toString()); SVGGroupArea area = SVGGroupAreaFactory.getGroup(group, groupArea, Assessable.getWorst(groupStatuses), debug); groupAreas.add(area); return area.render(); @@ -183,7 +183,7 @@ private List getRelations(LayoutedComponent layouted) { private SVGRelation getSvgRelation(LayoutedComponent layoutedItem, Item source, Relation rel) { Optional bestPath = hexMap.getPath(source, rel.getTarget()); if (bestPath.isPresent()) { - List statusValues = assessment.getResults().get(source.getFullyQualifiedIdentifier()); + List statusValues = assessment.getResults().get(source.getFullyQualifiedIdentifier().toString()); StatusValue worst = Assessable.getWorst(statusValues); SVGRelation svgRelation = new SVGRelation(bestPath.get(), layoutedItem.getColor(), rel, worst); LOGGER.debug("Added path for item {} relation {} -> {}", source, rel.getSource(), rel.getTarget()); diff --git a/src/main/java/de/bonndan/nivio/search/SearchIndex.java b/src/main/java/de/bonndan/nivio/search/SearchIndex.java index a61399632..3de7aa8b0 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchIndex.java +++ b/src/main/java/de/bonndan/nivio/search/SearchIndex.java @@ -85,14 +85,14 @@ public void indexForSearch(@NonNull final Landscape landscape, @NonNull final As /** * Creates a search index based in a snapshot of current items state (later modifications won't be shown). */ - private void indexItems(Set items, Map> results) { + private void indexItems(Set items, Map> results) { try { FacetsConfig config = SearchDocumentFactory.getConfig(); TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoIndex, IndexWriterConfig.OpenMode.CREATE); IndexWriter writer = new IndexWriter(searchIndex, new IndexWriterConfig(new StandardAnalyzer())); writer.deleteAll(); for (Item item : items) { - writer.addDocument(config.build(taxoWriter, from(item, results.get(item.getFullyQualifiedIdentifier())))); + writer.addDocument(config.build(taxoWriter, from(item, results.get(item.getFullyQualifiedIdentifier().toString())))); } IOUtils.close(writer, taxoWriter); } catch (IOException e) { diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java index 70d758392..bf6cd5a9f 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java @@ -2,7 +2,6 @@ import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; @@ -34,7 +33,7 @@ void getSummaryHighest() { .max(new StatusValue.Comparator()) .orElse(new StatusValue(SUMMARY_LABEL, Status.UNKNOWN)); - StatusValue summary = StatusValue.summary(SUMMARY_LABEL + "." + child1.getIdentifier(), max); + StatusValue summary = StatusValue.summary(SUMMARY_LABEL + "." + child1.getAssessmentIdentifier(), max); assertNotNull(summary); assertEquals(Status.RED, summary.getStatus()); assertEquals("worst", summary.getMessage()); @@ -84,16 +83,16 @@ protected List getStatusValues(String value, String message) { }); //when - Map> assessmentMap = item.applyKPIs(kpis); + Map> assessmentMap = item.applyKPIs(kpis); //then assertNotNull(assessmentMap); - List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier()); + List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(itemStatuses); - StatusValue statusValue = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.bar")).findFirst().orElse(null); + StatusValue statusValue = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.test/foo/bar")).findFirst().orElse(null); assertNotNull(statusValue); - assertEquals("summary.bar", statusValue.getField()); + assertEquals("summary.test/foo/bar", statusValue.getField()); StatusValue something = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals("something")).findFirst().orElse(null); assertNotNull(something); @@ -119,11 +118,11 @@ protected List getStatusValues(String value, String message) { }); //when - Map> assessmentMap = item.applyKPIs(kpis); + Map> assessmentMap = item.applyKPIs(kpis); //then assertNotNull(assessmentMap); - List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier()); + List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(itemStatuses); assertThat(itemStatuses).hasSize(2); @@ -142,7 +141,7 @@ public void groupSummary() { item2.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_STATUS), Status.RED.getName()); item2.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "not so bad"); - Group foo = new Group("foo", "landscapeIdentifier"); + Group foo = new Group("foo", "test"); foo.addItem(item); foo.addItem(item2); @@ -155,19 +154,19 @@ protected List getStatusValues(String value, String message) { }); //when - Map> groupStatuses = foo.applyKPIs(kpis); + Map> groupStatuses = foo.applyKPIs(kpis); //then - List statusValues = groupStatuses.get(foo.getFullyQualifiedIdentifier()); + List statusValues = groupStatuses.get(foo.getFullyQualifiedIdentifier().toString()); assertNotNull(statusValues); //group summary - StatusValue statusValue = statusValues.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.foo")).findFirst().orElse(null); + StatusValue statusValue = statusValues.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.test/foo")).findFirst().orElse(null); assertNotNull(statusValue); - assertEquals("summary.foo", statusValue.getField()); + assertEquals("summary.test/foo", statusValue.getField()); assertEquals(Status.BROWN, statusValue.getStatus()); assertEquals("very bad", statusValue.getMessage()); - assertEquals("summary.bar", statusValue.getMaxField()); + assertEquals("summary.test/foo/bar", statusValue.getMaxField()); } @Test @@ -191,10 +190,10 @@ protected List getStatusValues(String value, String message) { }); //when - Map> statuses = item.applyKPIs(kpis); + Map> statuses = item.applyKPIs(kpis); //then - List statusValues = statuses.get(item.getFullyQualifiedIdentifier()); + List statusValues = statuses.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(statusValues); assertEquals(4, statusValues.size()); StatusValue summary = statusValues.get(0); @@ -207,9 +206,9 @@ protected List getStatusValues(String value, String message) { assertThat(s2.getStatus().compareTo(s3.getStatus())).isEqualTo(1); } - class TestAssessable implements Assessable { + static class TestAssessable implements Assessable { - private Set statusValues = new HashSet<>(); + private final Set statusValues = new HashSet<>(); private final List children; TestAssessable(List children) { @@ -221,48 +220,13 @@ public Set getAdditionalStatusValues() { return statusValues; } - void setStatusValue(@NonNull StatusValue statusValue) { - getAdditionalStatusValues().add(statusValue); - } - - @Override - public String getIdentifier() { - return "test"; - } - - @Override - public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { - return FullyQualifiedIdentifier.build("test", null, null); - } - - @Override - public String getName() { - return "test"; - } - @Override - public String getContact() { + public String getAssessmentIdentifier() { return "test"; } - @Override - public String getDescription() { - return "test"; - } - - @Override - public String getOwner() { - return null; - } - - @Override - public String getIcon() { - return null; - } - - @Override - public String getColor() { - return null; + void setStatusValue(@NonNull StatusValue statusValue) { + getAdditionalStatusValues().add(statusValue); } @Override diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java index 5430b6b87..f9c9759b9 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java @@ -10,7 +10,7 @@ import java.util.*; -import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENTERRORNULL; +import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENT_ERROR_NULL; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -43,8 +43,8 @@ void getAssessmentFromFactoryLandscape() { void getAssessmentFromFactoryMap() { var fqi = FullyQualifiedIdentifier.build("test1", "test2", "test3"); var statusList = new ArrayList(); - var results = new HashMap>(); - results.put(fqi, statusList); + var results = new HashMap>(); + results.put(fqi.toString(), statusList); var assessment = AssessmentFactory.createAssessment(results); assertThat(assessment.getClass()).isEqualTo(Assessment.class); } @@ -53,10 +53,10 @@ void getAssessmentFromFactoryMap() { @Test void testNullValues() { var exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment(null, null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Landscape) null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); - exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Map>) null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); + exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Map>) null)); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java index 653a99a45..092e68359 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java @@ -9,7 +9,7 @@ import java.util.Set; -import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENTERRORNULL; +import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENT_ERROR_NULL; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -56,7 +56,7 @@ void testGetNonExistingElement() { @Test void testIllegalArgumentExceptionGet() { var exception = assertThrows(NullPointerException.class, () -> assessmentRepository.createAssessment(null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); } } From 8082f7d08987c42fe402285dc71ba44890d473b0 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 13:24:21 +0200 Subject: [PATCH 031/310] [#565] relations assessable --- .../de/bonndan/nivio/assessment/Assessable.java | 4 +--- src/main/java/de/bonndan/nivio/model/Item.java | 4 ++++ .../java/de/bonndan/nivio/model/Relation.java | 5 +++++ .../java/de/bonndan/nivio/model/ItemTest.java | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessable.java b/src/main/java/de/bonndan/nivio/assessment/Assessable.java index 6880bb460..1af4c248e 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessable.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessable.java @@ -37,9 +37,7 @@ public interface Assessable { * Returns the components to be assessed before this (e.g. group items). */ @JsonIgnore - default List getChildren() { - return new ArrayList<>(); - } + List getChildren(); /** * Recursively applies the {@link KPI}s to children and self. diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 7b0cd62c2..efba20cf3 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -306,6 +306,10 @@ public String getAssessmentIdentifier() { return getFullyQualifiedIdentifier().toString(); } + @Override + public List getChildren() { + return getRelations().stream().filter(relation -> relation.getSource().equals(this)).collect(Collectors.toList()); + } /** * Compare on field level against a newer version. diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 10e03e2e3..0cb827451 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -125,6 +125,11 @@ public String getAssessmentIdentifier() { return getIdentifier(); } + @Override + public List getChildren() { + return new ArrayList<>(); + } + @JsonInclude(JsonInclude.Include.NON_NULL) static class ApiModel { diff --git a/src/test/java/de/bonndan/nivio/model/ItemTest.java b/src/test/java/de/bonndan/nivio/model/ItemTest.java index faf3ca5f5..9c9cbc7b3 100644 --- a/src/test/java/de/bonndan/nivio/model/ItemTest.java +++ b/src/test/java/de/bonndan/nivio/model/ItemTest.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.model; +import de.bonndan.nivio.assessment.Assessable; import org.junit.jupiter.api.Test; import java.util.List; @@ -158,4 +159,19 @@ public void setRelations() { s1.setRelations(Set.of(RelationFactory.createForTesting(s1, s3))); assertThat(s1.getRelations()).hasSize(1); } + + @Test + public void relationsAsAssessmentChildren() { + + Item s1 = getTestItemBuilder("g1", "a").build(); + Item s2 = getTestItemBuilder("g2", "b").build(); + Relation forTesting = RelationFactory.createForTesting(s1, s2); + s1.addOrReplace(forTesting); + + //when + List children = s1.getChildren(); + assertThat(children).hasSize(1); + assertThat(children.get(0)).isEqualTo(forTesting); + + } } From b95bbe1c9b5cb0880172949992e9fb8d7c5b0efb Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 24 Jun 2021 09:12:02 +0200 Subject: [PATCH 032/310] add a GitHubProperties constructor for testing --- .../nivio/input/external/github/GitHubProperties.java | 7 +++++++ .../nivio/input/external/gitlab/GitLabConfigTest.java | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java index 32d380b4c..0c72542ed 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java @@ -13,6 +13,13 @@ public class GitHubProperties { private String oauth; private String jwt; + public GitHubProperties(String login, String password, String oauth, String jwt) { + this.login = login; + this.password = password; + this.oauth = oauth; + this.jwt = jwt; + } + public String getLogin() { return login; } diff --git a/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java new file mode 100644 index 000000000..bb79ae855 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java @@ -0,0 +1,4 @@ +import static org.junit.jupiter.api.Assertions.*; +class GitLabConfigTest { + +} \ No newline at end of file From 2ac108de7048e90c0089ebb80dd4fb464cb585ed Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 24 Jun 2021 09:13:20 +0200 Subject: [PATCH 033/310] add new methods for testing --- .../external/github/GitHubConfigTest.java | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java index 7bbd5b11b..10c22ab93 100644 --- a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java @@ -8,7 +8,60 @@ class GitHubConfigTest { @Test void returnsNullIfNoConfig() { - GitHubConfig gitHubConfig = new GitHubConfig(); + GitHubProperties gitHubProperties = null; + GitHubConfig gitHubConfig = new GitHubConfig(null); assertNull(gitHubConfig.getGitHub()); } + @Test + void groupedAssertions(){ + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + // in a grouped assertion all assertions are executed, and any failures will be reported together + assertAll("gitHubProperties",()-> assertEquals("kohsuke",gitHubProperties.getLogin()), + ()->assertEquals("012345678",gitHubProperties.getPassword()), + ()-> assertEquals("4d98173f7c075527cb64878561d1fe70",gitHubProperties.getOauth()), + ()-> assertEquals("my_jwt_token",gitHubProperties.getJwt())); + + } + @Test + void dependentAssertions(){ + // within a code block, if an assertion fails the subsequent code in the + // same block will be skipped + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + assertAll("properties", + ()->{String login = gitHubProperties.getLogin(); + assertNotNull(login); + // executed only if the previous assertion is valid + assertAll("login", + ()-> assertTrue(login.startsWith("ko")), + ()-> assertTrue(login.endsWith("ke"))); + }, + ()->{String password = gitHubProperties.getPassword(); + assertNotNull(password); + // executed only if the previous assertion is valid + assertAll("password", + ()-> assertTrue(password.contains("45")), + ()-> assertTrue(password.length()==9)); + + }, + ()->{String oauth = gitHubProperties.getOauth(); + assertNotNull(oauth); + // executed only if the previous assertion is valid + assertAll("oauth", + ()-> assertTrue(oauth.contains("cb648")), + ()->assertTrue(oauth.endsWith("0"))); + }, + ()->{String jwt = gitHubProperties.getJwt(); + assertNotNull(jwt); + // executed only if the previous assertion is valid + assertAll("jwt", + ()->assertTrue(jwt.length()==12), + ()->assertTrue(jwt.endsWith("ken")) + ); + + } + + ); + + } + } \ No newline at end of file From f6101b1d0b21eb66a75694175c9f343d3009ae08 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 24 Jun 2021 09:14:28 +0200 Subject: [PATCH 034/310] add two constructors for testing --- .../nivio/input/external/gitlab/GitLabProperties.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java index 123939897..35d7e28c2 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -11,6 +11,17 @@ public class GitLabProperties { private String username; private String password; + public GitLabProperties() { + + } + + public GitLabProperties(String hostUrl, String personalAccessToken, String username, String password) { + this.hostUrl = hostUrl; + this.personalAccessToken = personalAccessToken; + this.username = username; + this.password = password; + } + public String getHostUrl() { return hostUrl; } From 4d16f0fc99d747406c855ad29ff1896504e43838 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 24 Jun 2021 09:18:31 +0200 Subject: [PATCH 035/310] add methods for testing --- .../external/gitlab/GitLabConfigTest.java | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java index bb79ae855..6e14ab113 100644 --- a/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java @@ -1,4 +1,70 @@ +package de.bonndan.nivio.input.external.gitlab; + +import org.junit.jupiter.api.Test; +import java.util.Optional; + +import static java.util.Optional.*; import static org.junit.jupiter.api.Assertions.*; + class GitLabConfigTest { - + + + @Test + void returnsNullIfNoConfig() + { + GitLabProperties gitLabProperties = new GitLabProperties(); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); + assertNull(gitLabConfig.getGitLabAPI()); + } + + + @Test + void groupedAssertions(){ + GitLabProperties gitLabProperties = new GitLabProperties("http://gitlab.example.com","token-string-here123","abracadabra","123456789"); + // in a grouped assertion all assertions are executed, and any failures will be reported together + assertAll("hostUrl",()->assertEquals("http://gitlab.example.com",gitLabProperties.getHostUrl()), + ()->assertEquals("token-string-here123",gitLabProperties.getPersonalAccessToken()), + ()->assertEquals("abracadabra",gitLabProperties.getUsername()), + ()->assertEquals("123456789",gitLabProperties.getPassword()) + ); + } + + + @Test + void dependentAssertions(){ + // with a code block, if an assertion fails the subsequent code in the same block will be skipped + GitLabProperties gitLabProperties = new GitLabProperties("http://gitlab.example.com","token-string-here123","abracadabra","123456789"); + assertAll("properties", + ()->{ String hostUrl = gitLabProperties.getHostUrl(); + assertNotNull(hostUrl); + // executed only if the previous assertion is valid + assertAll("Host Url", + ()->assertFalse(hostUrl.isEmpty()), + ()->assertTrue(hostUrl.contains("exa"))); + }, + ()->{String personalAccessToken = gitLabProperties.getPersonalAccessToken(); + assertNotNull(personalAccessToken); + // executed only if the previous assertion is valid + assertAll("Personal Access Token", + ()->assertTrue(personalAccessToken.endsWith("123")), + ()->assertTrue(personalAccessToken.startsWith("tok"))); + }, + ()->{String username = gitLabProperties.getUsername(); + assertNotNull(username); + // executed only if the previous assertion is valid + assertAll("username", + ()->assertTrue(username.contains("dabra")), + ()->assertFalse(username.isEmpty())); + }, + ()->{String password = gitLabProperties.getPassword(); + assertNotNull(password); + // executed only if the previous assertion is valid + assertAll("password", + ()->assertFalse(password.contains("xyz")), + ()->assertTrue(password.endsWith("89"))); + } + + ); + } + } \ No newline at end of file From 88636ab0591ee750b33b6baaf5bd3b3441c306f2 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 15:44:59 +0200 Subject: [PATCH 036/310] [#585] fix for asessment creation --- .../nivio/search/SearchIndexingEventListener.java | 10 ++-------- .../nivio/search/SearchIndexingEventListenerTest.java | 3 ++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java b/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java index 7f7977aa3..a160a1514 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java +++ b/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java @@ -24,13 +24,7 @@ public void onProcessingFinishedEvent(@NonNull ProcessingFinishedEvent event) { final Landscape landscape = event.getLandscape(); final SearchIndex searchIndex = landscape.getSearchIndex(); - //see https://github.com/dedica-team/nivio/issues/519 - var assessment = assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()); - if (assessment.isEmpty()) { - searchIndex.indexForSearch(landscape, assessmentRepository.createAssessment(landscape)); - } else { - searchIndex.indexForSearch(landscape, assessment.get()); - } - + //we create a new assessment here, since the landscape has changed + searchIndex.indexForSearch(landscape, assessmentRepository.createAssessment(landscape)); } } diff --git a/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java b/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java index 290efbcd3..a57a9d336 100644 --- a/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java +++ b/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java @@ -34,7 +34,7 @@ void setUp() { void onProcessingFinishedEvent() { //given var assessment = AssessmentFactory.createAssessment(landscape); - when(assessmentRepository.getAssessment(Mockito.any())).thenReturn(Optional.of(assessment)); + when(assessmentRepository.createAssessment(eq(landscape))).thenReturn(assessment); ProcessingFinishedEvent e = new ProcessingFinishedEvent(new LandscapeDescription("foo"), landscape, new ProcessingChangelog()); SearchIndex searchIndex = mock(SearchIndex.class); when(landscape.getSearchIndex()).thenReturn(searchIndex); @@ -49,6 +49,7 @@ void onProcessingFinishedEvent() { verify(landscape).getSearchIndex(); verify(landscape).getKpis(); verify(landscape).applyKPIs(any()); + verify(assessmentRepository).createAssessment(eq(landscape)); verify(searchIndex).indexForSearch(eq(landscape), any(Assessment.class)); } From 063069affe1fa5482e0730bcf4137523e14f963f Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 21 Jun 2021 17:26:02 +0200 Subject: [PATCH 037/310] group description has anySetter to accept arbitrary labels --- .../nivio/input/dto/GroupDescription.java | 13 +++++- .../nivio/input/dto/ItemDescription.java | 30 ++----------- .../java/de/bonndan/nivio/model/Labeled.java | 44 +++++++++++++++++++ .../de/bonndan/nivio/model/LabeledTest.java | 23 +++++++++- 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java index 008b65095..19bf732ef 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java @@ -1,9 +1,10 @@ package de.bonndan.nivio.input.dto; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.Link; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; @@ -43,6 +44,7 @@ public class GroupDescription implements ComponentDescription { @Schema(hidden = true) private String environment; + @NonNull public String getIdentifier() { return identifier; } @@ -52,6 +54,7 @@ public void setIdentifier(String identifier) { } @Schema(hidden = true, description = "Computed value") + @NonNull public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { return FullyQualifiedIdentifier.build(environment, identifier, null); } @@ -131,6 +134,8 @@ public Map getLabels() { return labels; } + @Override + @JsonAnyGetter public String getLabel(String key) { return labels.get(key); } @@ -139,6 +144,12 @@ public void setLabel(String key, String value) { labels.put(key, value); } + @JsonAnySetter + @Override + public void setLabel(@NonNull String key, Object value) { + ComponentDescription.super.setLabel(key, value); + } + public void setEnvironment(String environment) { this.environment = environment; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index aed35edb9..9b48d7718 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -1,12 +1,10 @@ package de.bonndan.nivio.input.dto; - import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.*; import io.swagger.v3.oas.annotations.media.Schema; @@ -327,31 +325,9 @@ public void setLabel(String key, String value) { } @JsonAnySetter - public void setLabel(String key, Object value) { - if (value instanceof String) { - labels.put(key.toLowerCase(), (String) value); - return; - } - if (value instanceof String[]) { - Arrays.stream(((String[]) value)).forEach(s -> setPrefixed(key, s)); - return; - } - - if (value instanceof List) { - try { - //noinspection unchecked,rawtypes - ((List) value).forEach(s -> setPrefixed(key, (String) s)); - return; - } catch (ClassCastException e) { - throw new ProcessingException(String.format("Cannot set '%s' to list '%s'. Is this a list-like structure", key, value), e); - } - } - - if (value instanceof Map) { - throw new IllegalArgumentException(String.format("Cannot use the value of '%s' as map ('%s'). Please check the spelling of", key, value)); - } - - labels.put(key, String.valueOf(value)); + @Override + public void setLabel(@NonNull String key, Object value) { + ComponentDescription.super.setLabel(key, value); } /** diff --git a/src/main/java/de/bonndan/nivio/model/Labeled.java b/src/main/java/de/bonndan/nivio/model/Labeled.java index 2a5ed1d5f..392d98ebe 100644 --- a/src/main/java/de/bonndan/nivio/model/Labeled.java +++ b/src/main/java/de/bonndan/nivio/model/Labeled.java @@ -3,6 +3,7 @@ import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; import de.bonndan.nivio.input.AppearanceProcessor; +import de.bonndan.nivio.input.ProcessingException; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -76,6 +77,49 @@ default void setLabel(Label key, String value) { setLabel(key.name().toLowerCase(), value); } + /** + * Any-setter default implementation for deserialization. + * + * @param key label key + * @param value label value (string|string[]|number|list|map) + */ + default void setLabel(@NonNull final String key, final Object value) { + if (StringUtils.isEmpty(key)) { + throw new IllegalArgumentException("Label key is empty."); + } + + if (value instanceof String) { + getLabels().put(key.toLowerCase(), (String) value); + return; + } + + if (value instanceof Number) { + getLabels().put(key.toLowerCase(), String.valueOf(value)); + return; + } + + if (value instanceof String[]) { + Arrays.stream(((String[]) value)).forEach(s -> setPrefixed(key, s)); + return; + } + + if (value instanceof List) { + try { + //noinspection unchecked,rawtypes + ((List) value).forEach(s -> setPrefixed(key, (String) s)); + return; + } catch (ClassCastException e) { + throw new ProcessingException(String.format("Cannot set '%s' to list '%s'. Is this a list-like structure", key, value), e); + } + } + + if (value instanceof Map) { + throw new IllegalArgumentException(String.format("Cannot use the value of '%s' as map ('%s'). Please check the spelling of", key, value)); + } + + getLabels().put(key, String.valueOf(value)); + } + static Map withPrefix(String prefix, Map all) { return all.entrySet().stream() .filter(stringStringEntry -> stringStringEntry.getValue() != null) diff --git a/src/test/java/de/bonndan/nivio/model/LabeledTest.java b/src/test/java/de/bonndan/nivio/model/LabeledTest.java index efa47af81..debd1b8fb 100644 --- a/src/test/java/de/bonndan/nivio/model/LabeledTest.java +++ b/src/test/java/de/bonndan/nivio/model/LabeledTest.java @@ -3,11 +3,13 @@ import de.bonndan.nivio.input.dto.ItemDescription; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; class LabeledTest { @@ -50,7 +52,7 @@ public void setLabelsDoesNotOverwriteExistingOnes() { itemDescription.setLabels(Map.of("one", "two")); assertEquals(2, itemDescription.getLabels().size()); - assertTrue(itemDescription.getLabels().containsKey( "foo")); + assertTrue(itemDescription.getLabels().containsKey("foo")); } @Test @@ -65,7 +67,7 @@ public void withoutPrefixes() { assertThat(stringStringMap).isNotNull(); assertThat(stringStringMap.size()).isEqualTo(2); assertThat(stringStringMap.get(Label.costs.name())).isEqualTo("123"); - assertThat(stringStringMap.get(Label.network.name()+".foo")).isEqualTo("foo"); + assertThat(stringStringMap.get(Label.network.name() + ".foo")).isEqualTo("foo"); } @Test @@ -112,4 +114,21 @@ void diffIgnoresAppearanceLabels() { //then assertThat(diff).isEmpty(); } + + @Test + public void anySetterRejectsEmptyKey() { + ItemDescription i = new ItemDescription(); + assertThatThrownBy(() -> i.setLabel("", new ArrayList())).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void anySetterAcceptsNumber() { + ItemDescription i = new ItemDescription(); + + //when + i.setLabel("foo", 1L); + + //then + assertThat(i.getLabel("foo")).isEqualTo("1"); + } } \ No newline at end of file From 0e7490014ae15d52e38054eee65dc26925ab3322 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 21 Jun 2021 17:34:29 +0200 Subject: [PATCH 038/310] cleanup --- src/test/java/de/bonndan/nivio/model/LabeledTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/model/LabeledTest.java b/src/test/java/de/bonndan/nivio/model/LabeledTest.java index debd1b8fb..30594f781 100644 --- a/src/test/java/de/bonndan/nivio/model/LabeledTest.java +++ b/src/test/java/de/bonndan/nivio/model/LabeledTest.java @@ -116,13 +116,13 @@ void diffIgnoresAppearanceLabels() { } @Test - public void anySetterRejectsEmptyKey() { + void anySetterRejectsEmptyKey() { ItemDescription i = new ItemDescription(); assertThatThrownBy(() -> i.setLabel("", new ArrayList())).isInstanceOf(IllegalArgumentException.class); } @Test - public void anySetterAcceptsNumber() { + void anySetterAcceptsNumber() { ItemDescription i = new ItemDescription(); //when From e3a022f3ec82a6e96d795a879de651ae8aeab0b9 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 16:56:41 +0200 Subject: [PATCH 039/310] [#584] do not show links to unlisted items in owner report --- .../de/bonndan/nivio/output/docs/HtmlGenerator.java | 10 ++++++++-- .../nivio/output/docs/OwnersReportGenerator.java | 2 +- .../de/bonndan/nivio/output/docs/ReportGenerator.java | 9 +++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java index 9258ac27f..831a5f968 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java @@ -16,6 +16,7 @@ import org.springframework.util.StringUtils; import java.net.URL; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; @@ -69,7 +70,7 @@ protected ContainerTag getHead(Landscape landscape) { ); } - protected ContainerTag writeItem(Item item, Assessment assessment) { + protected ContainerTag writeItem(Item item, Assessment assessment, Collection allItems) { boolean hasRelations = !item.getRelations().isEmpty(); boolean hasInterfaces = !item.getInterfaces().isEmpty(); String groupColor = "#" + Color.nameToRGB(item.getGroup(), Color.GRAY); @@ -147,11 +148,16 @@ protected ContainerTag writeItem(Item item, Assessment assessment) { Item end = (df.getSource().equals(item)) ? df.getTarget() : df.getSource(); + ContainerTag endTag = span(end.toString()); + if (allItems.contains(end)) { + endTag = a(end.toString()).attr("href", "#" + end.getFullyQualifiedIdentifier()); + } + return li(rawHtml((df.getType() != null ? df.getType() : "") + " " + ifPresent(df.getFormat()) + " " + ifPresent(df.getDescription()) + direction), - a(end.toString()).attr("href", "#" + end.getFullyQualifiedIdentifier())); + endTag); }) ) ), diff --git a/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java index ea2c3fe89..b83673c6d 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java @@ -56,7 +56,7 @@ private String writeOwnerGroups(GroupedBy ownerGroups, Assessment assessment) { builder.append( h2("Owner: " + owner).render() ); - List collect = items.stream().map(item -> div(writeItem(item, assessment)).withClass("col-sm")).collect(Collectors.toList()); + List collect = items.stream().map(item -> div(writeItem(item, assessment, items)).withClass("col-sm")).collect(Collectors.toList()); builder.append(div().withClass("row").with(collect).render()); }); diff --git a/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java index 1aa2a1abf..abc1e513a 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java @@ -2,6 +2,7 @@ import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.output.Color; import de.bonndan.nivio.output.LocalServer; @@ -12,6 +13,7 @@ import java.util.Map; import java.util.Objects; +import java.util.Set; import static de.bonndan.nivio.output.FormatUtils.nice; import static de.bonndan.nivio.output.map.MapController.MAP_SVG_ENDPOINT; @@ -20,8 +22,6 @@ /** * Generates a report containing all landscape groups and items. - * - * */ public class ReportGenerator extends HtmlGenerator { @@ -50,7 +50,8 @@ private String writeLandscape(final Landscape landscape, final Assessment assess private String writeGroups(Landscape landscape, Assessment assessment) { final StringBuilder builder = new StringBuilder(); - Map groups = landscape.getGroups(); + final Map groups = landscape.getGroups(); + final Set all = landscape.getItems().all(); groups.forEach((s, groupItem) -> { String color = "#" + Color.getGroupColor(groupItem); builder.append( @@ -59,7 +60,7 @@ private String writeGroups(Landscape landscape, Assessment assessment) { ); builder.append( div().attr("class", "group") - .with(groupItem.getItems().stream().map(item -> this.writeItem(item, assessment))) + .with(groupItem.getItems().stream().map(item -> this.writeItem(item, assessment, all))) .render() ); }); From d523d0ac82256237c817192ac997aaf9c7715c85 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 16:59:49 +0200 Subject: [PATCH 040/310] cleanup --- .../de/bonndan/nivio/input/external/LinkHandlerFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java index 087d99d5d..8e20049fe 100644 --- a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java +++ b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java @@ -52,7 +52,7 @@ private Optional createHandler(String key, Class Date: Wed, 23 Jun 2021 08:05:06 +0200 Subject: [PATCH 041/310] [#562] message template for custom KPIs --- docs/source/assessment.rst | 6 +- docs/source/schema/Models/KPIConfig.rst | 5 + docs/source/schema/spec.json | 134 +++++++++--------- src/main/app/src/interfaces.ts | 1 - .../nivio/assessment/kpi/AbstractKPI.java | 21 ++- .../nivio/assessment/kpi/CustomKPI.java | 18 ++- .../nivio/assessment/kpi/KPIConfig.java | 6 +- .../nivio/assessment/kpi/LifecycleKPI.java | 13 +- .../nivio/assessment/kpi/CustomKPITest.java | 21 ++- .../assessment/kpi/LifecycleKPITest.java | 2 +- src/test/resources/example/pet_clinic.yml | 2 +- 11 files changed, 128 insertions(+), 101 deletions(-) diff --git a/docs/source/assessment.rst b/docs/source/assessment.rst index dafe19995..81381d43b 100644 --- a/docs/source/assessment.rst +++ b/docs/source/assessment.rst @@ -57,7 +57,10 @@ Custom KPIs Custom KPIs can be configured in the landscape config using ranges and/or matchers (regular expressions) and applied to everything having labels. In the example below a KPI ``monthlyCosts`` is defined, using ranges on the label ``costs``, and the KPI ``myEval`` evaluates a -label ``foo``. Both ranges (inclusive lower and upper limits) and matchers are separated by semicolon. +label ``foo``. + +* Both ranges (inclusive lower and upper limits) and matchers are separated by semicolon. +* The displayed message can be customized by a template. The placeholder for the value is '%s'. .. code-block:: yaml :linenos: @@ -70,6 +73,7 @@ label ``foo``. Both ranges (inclusive lower and upper limits) and matchers are s monthlyCosts: description: Evaluates the monthly maintenance costs label: costs + messageTemplate: "Monthly costs: $%s" ranges: GREEN: 0;99.999999 YELLOW: 100;199.999999 diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index dc2006360..8838e6fc9 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -23,6 +23,11 @@ The configuration of landscape specific key performance indicators that derive s - Key of the label to evaluate - optional, defaults to null - costs + * - messageTemplate + - String + - Template for the displayed message, containing a placeholder for the assessed value '%s + - optional, defaults to null + - The current value is: %s * - ranges - Map - A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 4033798f9..60951921a 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -191,78 +191,71 @@ "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", "example" : "4400FF" }, - "address": { - "type": "string", - "description": "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." - }, - "type": { - "type": "string", - "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - "example": "service|database|volume" - }, - "lifecycle": { - "type": "string", - "description": "The lifecycle state of an item.", - "writeOnly": true, - "enum": [ - "PLANNED", - "INTEGRATION", - "TEST", - "PRODUCTION", - "END_OF_LIFE", - "EOL" - ] - }, - "status": { - "type": "array", - "description": "A list of statuses that works like hardcoded KPIs.", - "writeOnly": true, - "items": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A list of statuses that works like hardcoded KPIs." + "address" : { + "type" : "string", + "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." + }, + "type" : { + "type" : "string", + "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", + "example" : "service|database|volume" + }, + "status" : { + "type" : "array", + "description" : "A list of statuses that works like hardcoded KPIs.", + "writeOnly" : true, + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A list of statuses that works like hardcoded KPIs." }, - "description": "A list of statuses that works like hardcoded KPIs." + "description" : "A list of statuses that works like hardcoded KPIs." } }, - "statuses": { - "type": "array", - "description": "A list of statuses that works like hardcoded KPIs.", - "writeOnly": true, - "items": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A list of statuses that works like hardcoded KPIs." + "statuses" : { + "type" : "array", + "description" : "A list of statuses that works like hardcoded KPIs.", + "writeOnly" : true, + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A list of statuses that works like hardcoded KPIs." }, - "description": "A list of statuses that works like hardcoded KPIs." + "description" : "A list of statuses that works like hardcoded KPIs." } }, - "frameworks": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "The parts used to create the item. Usually refers to technical frameworks.", - "example": "java: 8" + "frameworks" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "example" : "java: 8" }, - "description": "The parts used to create the item. Usually refers to technical frameworks.", - "writeOnly": true, - "example": "java: 8" - }, - "tags": { - "type": "array", - "items": { - "type": "string" + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "writeOnly" : true, + "example" : "java: 8" + }, + "lifecycle" : { + "type" : "string", + "description" : "The lifecycle state of an item.", + "writeOnly" : true, + "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] + }, + "tags" : { + "type" : "array", + "items" : { + "type" : "string" } }, - "links": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/Link" + "links" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/Link" }, - "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example": "github: https://github.com/dedica-team/nivio" + "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example" : "github: https://github.com/dedica-team/nivio" } }, "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." @@ -279,6 +272,11 @@ "description" : "Key of the label to evaluate", "example" : "costs" }, + "messageTemplate" : { + "type" : "string", + "description" : "Template for the displayed message, containing a placeholder for the assessed value '%s", + "example" : "The current value is: %s" + }, "ranges" : { "type" : "object", "additionalProperties" : { @@ -409,12 +407,6 @@ }, "description" : "Additional labels for the landscape." }, - "color": { - "type": "string" - }, - "icon": { - "type": "string" - }, "items" : { "type" : "array", "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", @@ -427,6 +419,12 @@ "type" : "boolean", "description" : "marks that the landscape is not complete, but an update" }, + "icon" : { + "type" : "string" + }, + "color" : { + "type" : "string" + }, "links" : { "type" : "object", "additionalProperties" : { diff --git a/src/main/app/src/interfaces.ts b/src/main/app/src/interfaces.ts index 94f566112..da85809aa 100644 --- a/src/main/app/src/interfaces.ts +++ b/src/main/app/src/interfaces.ts @@ -48,7 +48,6 @@ export interface IKpis { export interface IKpi { description?: string; label?: string; - messageLabel?: string; ranges?: IRanges; matches?: IMatches; enabled?: boolean; diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java index eb688910d..dca73e8b3 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java @@ -6,6 +6,7 @@ import org.springframework.lang.Nullable; import java.util.List; +import java.util.Objects; import java.util.function.Function; /** @@ -13,25 +14,31 @@ */ public abstract class AbstractKPI implements KPI { - protected Function valueFunction; - protected Function msgFunction; + protected String messageTemplate = "%s"; private String description; private boolean enabled = true; + protected Function valueFunction; + + @NonNull + protected Function msgFunction = component -> String.format(messageTemplate, valueFunction.apply(component)); + public AbstractKPI() { } /** - * @param valueFunction the label which is evaluated for status - * @param msgFunction the label which is used as optional message + * @param valueFunction a function returning the value to assess + * @param msgFunction a function returning the status message */ public AbstractKPI(@NonNull Function valueFunction, @Nullable Function msgFunction ) { - this.valueFunction = valueFunction; - this.msgFunction = msgFunction; + this.valueFunction = Objects.requireNonNull(valueFunction); + if (msgFunction != null) { + this.msgFunction = msgFunction; + } } /** @@ -47,7 +54,7 @@ public List getStatusValues(Assessable component) { throw new RuntimeException("Value function not initialized "); } String value = valueFunction.apply(component); - String message = msgFunction != null ? msgFunction.apply(component) : null; + String message = msgFunction.apply(component); return getStatusValues(value, message); } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java index 6fabae5ec..6cabba353 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java @@ -6,6 +6,7 @@ import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Labeled; import org.apache.commons.lang3.Range; +import org.apache.commons.lang3.StringUtils; import org.springframework.lang.Nullable; import java.util.*; @@ -32,7 +33,6 @@ public class CustomKPI extends AbstractKPI { private final Map>> matches = new HashMap<>(); protected String label; - protected String messageLabel = null; /** * @@ -48,7 +48,9 @@ public void init(KPIConfig kpiConfig) { label = kpiConfig.label; } this.setEnabled(kpiConfig.enabled); - messageLabel = kpiConfig.messageLabel; + if (!StringUtils.isEmpty(kpiConfig.messageTemplate)) { + messageTemplate = kpiConfig.messageTemplate; + } ranges = asRanges(kpiConfig.label, kpiConfig.ranges); addSpecsFromConfig(kpiConfig.matches); } @@ -59,12 +61,7 @@ public void init(KPIConfig kpiConfig) { } throw new RuntimeException("Custom KPIs can only evaluate labels (custom fields)."); }; - this.msgFunction = component -> { - if (component instanceof Labeled) { - return ((Labeled) component).getLabel(messageLabel); - } - return null; - }; + } @Override @@ -144,8 +141,9 @@ protected void addSpecsFromConfig(@Nullable Map input) { } protected void addSpecs(@Nullable Map statusPatterns) { - if (statusPatterns == null) + if (statusPatterns == null) { return; + } statusPatterns.forEach((status, strings) -> { List> specs = Arrays.stream(strings.split(SEPARATOR)).map(s -> { @@ -153,7 +151,7 @@ protected void addSpecs(@Nullable Map statusPatterns) { Pattern p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); return (Function) s1 -> p.matcher(s1).matches(); } catch (Exception e) { - throw new ProcessingException("Failed to initialize KPI " + this.label + " matcher pattern ", e); + throw new ProcessingException(String.format("Failed to initialize KPI %s matcher pattern ", this.label), e); } }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java index 338e3bcbc..cb95ac529 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java @@ -14,11 +14,11 @@ public class KPIConfig { @Schema(description = "Description of the purpose of the KPI") public String description; - @Schema(description = "Key of the label to evaluate", example = "costs") + @Schema(description = "Key of the label to evaluate", example = "costs", required = true) public String label; - @Schema(description = "What label content to display in the message", hidden = true) - public String messageLabel = null; + @Schema(description = "Template for the displayed message, containing a placeholder for the assessed value '%s", example = "The current value is: %s") + public String messageTemplate = null; /** * GREEN: 0;99.999999 diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java index f562ba348..a61b3a2e5 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java @@ -5,9 +5,7 @@ import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * This KPI evaluates the lifecycle label for "official" values (see {@link Lifecycle}). @@ -19,7 +17,10 @@ public class LifecycleKPI extends CustomKPI { public LifecycleKPI() { super(); label = Label.lifecycle.name(); - messageLabel = Label.lifecycle.name(); + msgFunction = component -> Optional.ofNullable(Lifecycle.from(valueFunction.apply(component))) + .map(lifecycle -> "Phase: " + lifecycle.name().toLowerCase(Locale.ROOT).replace("_", " ")) + .orElse("unknown"); + setDescription("This KPI evaluates the lifecycle label for known values (PLANNED, PRODUCTION)."); } @@ -27,10 +28,10 @@ public LifecycleKPI() { protected List getStatusValues(String value, String message) { Lifecycle lifecycle = Lifecycle.from(value); if (Lifecycle.PRODUCTION.equals(lifecycle)) { - return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.GREEN, value)); + return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.GREEN, message)); } if (Lifecycle.END_OF_LIFE.equals(lifecycle)) { - return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.ORANGE, value)); + return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.ORANGE, message)); } return new ArrayList<>(); diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java index 36b986ca0..52084a3ba 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java @@ -74,11 +74,10 @@ public void brokenRangeConfig() { } @Test - public void withMessageLabel() { + public void withoutMessageTemplate() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); - kpiConfig.messageLabel = "asMessageLabel"; test.init(kpiConfig); //when @@ -86,7 +85,23 @@ public void withMessageLabel() { //then assertNotNull(statusValue); - Assertions.assertEquals("10.1 foo", statusValue.getMessage()); + Assertions.assertEquals("10.1", statusValue.getMessage()); + } + + @Test + public void withMessageTemplate() { + CustomKPI test = new CustomKPI(); + + kpiConfig.ranges = getRangeMap(); + kpiConfig.messageTemplate = "foo bar: %s"; + test.init(kpiConfig); + + //when + StatusValue statusValue = test.getStatusValues(getComponent("10.1")).get(0); + + //then + assertNotNull(statusValue); + Assertions.assertEquals("foo bar: 10.1", statusValue.getMessage()); } @Test diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java index 9c48fceaa..ba6f16006 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java @@ -33,7 +33,7 @@ public void green() { assertEquals(1, statusValues.size()); StatusValue statusValue = statusValues.get(0); assertEquals(Status.GREEN, statusValue.getStatus()); - assertEquals("PRODUCTION", statusValue.getMessage()); + assertEquals("Phase: production", statusValue.getMessage()); } @Test diff --git a/src/test/resources/example/pet_clinic.yml b/src/test/resources/example/pet_clinic.yml index 5fc58cf6f..dfb282b11 100644 --- a/src/test/resources/example/pet_clinic.yml +++ b/src/test/resources/example/pet_clinic.yml @@ -9,7 +9,7 @@ config: radiation: description: Radiation level in mrem label: radiation - messageLabel: radiation + messageTemplate: "Level: %s mrem" ranges: GREEN: 0;99.999999 YELLOW: 100;199.999999 From 16584b478cafa6a3cd51aab5cf9fb6a4c64f54b1 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Wed, 23 Jun 2021 08:45:01 +0200 Subject: [PATCH 042/310] [#562] cleanup --- .../nivio/assessment/kpi/CustomKPITest.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java index 52084a3ba..930a520ca 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java @@ -21,13 +21,13 @@ class CustomKPITest { private KPIConfig kpiConfig; @BeforeEach - public void setup() { + void setup() { kpiConfig = new KPIConfig(); kpiConfig.label = LABEL; } @Test - public void testWithRanges1() { + void testWithRanges1() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); test.init(kpiConfig); @@ -37,7 +37,7 @@ public void testWithRanges1() { } @Test - public void testWithRanges2() { + void testWithRanges2() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); test.init(kpiConfig); @@ -47,7 +47,7 @@ public void testWithRanges2() { } @Test - public void testWithRanges3() { + void testWithRanges3() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); test.init(kpiConfig); @@ -57,7 +57,7 @@ public void testWithRanges3() { } @Test - public void testoutOfRange() { + void testoutOfRange() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); test.init(kpiConfig); @@ -66,7 +66,7 @@ public void testoutOfRange() { } @Test - public void brokenRangeConfig() { + void brokenRangeConfig() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); kpiConfig.ranges.put(Status.GREEN.name(), "0-12"); @@ -74,7 +74,7 @@ public void brokenRangeConfig() { } @Test - public void withoutMessageTemplate() { + void withoutMessageTemplate() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); @@ -89,7 +89,7 @@ public void withoutMessageTemplate() { } @Test - public void withMessageTemplate() { + void withMessageTemplate() { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); @@ -105,7 +105,7 @@ public void withMessageTemplate() { } @Test - public void brokenMatchesConfig() { + void brokenMatchesConfig() { Map matches = getMatches(); matches.put(Status.GREEN.name(), "0-12["); kpiConfig.matches = matches; @@ -115,7 +115,7 @@ public void brokenMatchesConfig() { } @Test - public void RangeOneNumber() { + void RangeOneNumber() { Map r2 = getRangeMap(); r2.put(Status.GREEN.name(), "0"); CustomKPI customKPI = new CustomKPI(); @@ -127,7 +127,7 @@ public void RangeOneNumber() { @Test - public void testWithMatches1() { + void testWithMatches1() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -136,7 +136,7 @@ public void testWithMatches1() { } @Test - public void testWithMatches2() { + void testWithMatches2() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -145,7 +145,7 @@ public void testWithMatches2() { } @Test - public void testWithMatches3() { + void testWithMatches3() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -154,7 +154,7 @@ public void testWithMatches3() { } @Test - public void testWithMatches4() { + void testWithMatches4() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -163,7 +163,7 @@ public void testWithMatches4() { } @Test - public void testWithMatches5() { + void testWithMatches5() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -172,7 +172,7 @@ public void testWithMatches5() { } @Test - public void noMatchIsEmpty() { + void noMatchIsEmpty() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); customKPI.init(kpiConfig); @@ -181,7 +181,7 @@ public void noMatchIsEmpty() { } @Test - public void testWithRangesAndMatches1() { + void testWithRangesAndMatches1() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); kpiConfig.ranges = getRangeMap(); @@ -191,7 +191,7 @@ public void testWithRangesAndMatches1() { } @Test - public void testWithRangesAndMatches2() { + void testWithRangesAndMatches2() { CustomKPI customKPI = new CustomKPI(); kpiConfig.matches = getMatches(); kpiConfig.ranges = getRangeMap(); From 739ea92b910863d8114fbb066613c28114ce3049 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Wed, 23 Jun 2021 09:01:52 +0200 Subject: [PATCH 043/310] [#562] cleanup --- .../nivio/assessment/kpi/CustomKPITest.java | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java index 930a520ca..cffec6ec5 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java @@ -7,9 +7,12 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import static de.bonndan.nivio.model.ItemFactory.getTestItem; @@ -26,34 +29,23 @@ void setup() { kpiConfig.label = LABEL; } - @Test - void testWithRanges1() { + @ParameterizedTest + @CsvSource({ + "2.58, green", + "0, green", + "10.1, yellow", + }) + void testWithRanges1(String value, String status) { CustomKPI test = new CustomKPI(); kpiConfig.ranges = getRangeMap(); test.init(kpiConfig); - StatusValue statusValue = test.getStatusValues(getComponent("2.58")).get(0); - assertNotNull(statusValue); - Assertions.assertEquals(Status.GREEN, statusValue.getStatus()); - } - @Test - void testWithRanges2() { - CustomKPI test = new CustomKPI(); - kpiConfig.ranges = getRangeMap(); - test.init(kpiConfig); - StatusValue statusValue = test.getStatusValues(getComponent("0")).get(0); - assertNotNull(statusValue); - Assertions.assertEquals(Status.GREEN, statusValue.getStatus()); - } + //when + StatusValue statusValue = test.getStatusValues(getComponent(value)).get(0); - @Test - void testWithRanges3() { - CustomKPI test = new CustomKPI(); - kpiConfig.ranges = getRangeMap(); - test.init(kpiConfig); - StatusValue statusValue = test.getStatusValues(getComponent("10.1")).get(0); + //then assertNotNull(statusValue); - Assertions.assertEquals(Status.YELLOW, statusValue.getStatus()); + Assertions.assertEquals(status, statusValue.getStatus().getName().toLowerCase(Locale.ROOT)); } @Test From bfc13cd50f3b0f294ce22ecd9db7f7634192a821 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Wed, 9 Jun 2021 12:27:38 +0200 Subject: [PATCH 044/310] [#565] csv input can read relations --- .../de/bonndan/nivio/input/dto/RelationDescription.java | 4 ++++ src/main/java/de/bonndan/nivio/model/Relation.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 42a8d76b1..28ab91de3 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -6,6 +6,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.NonNull; + import java.util.*; @Schema(description = "A directed relation between two landscape items. Also known as edge in a directed graph.") diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 0cb827451..30b265c5b 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -38,6 +38,12 @@ public class Relation implements Labeled, Assessable, Serializable { private final Map labels = new HashMap<>(); + public Relation(@NonNull final Item source, + @NonNull final Item target + ) { + this(source, target, null, null, null); + } + public Relation(@NonNull final Item source, @NonNull final Item target, final String description, From 7f46e29a76a19dc49af273cd3f701042222e9107 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sun, 20 Jun 2021 09:26:34 +0200 Subject: [PATCH 045/310] [#565] relations with labels --- .../java/de/bonndan/nivio/input/dto/RelationDescription.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 28ab91de3..22735af3f 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -8,10 +8,9 @@ import java.util.HashMap; import java.util.Map; -import org.springframework.lang.NonNull; - import java.util.*; + @Schema(description = "A directed relation between two landscape items. Also known as edge in a directed graph.") public class RelationDescription implements Labeled { From 6b76266e20ee27a6774711fabf8580abb027896a Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 22 Jun 2021 13:18:20 +0200 Subject: [PATCH 046/310] [#565] relations assessable --- .../java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java | 1 - src/main/java/de/bonndan/nivio/model/Relation.java | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java index dca73e8b3..2ef47d639 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java @@ -17,7 +17,6 @@ public abstract class AbstractKPI implements KPI { protected String messageTemplate = "%s"; private String description; - private boolean enabled = true; protected Function valueFunction; diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 30b265c5b..0cb827451 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -38,12 +38,6 @@ public class Relation implements Labeled, Assessable, Serializable { private final Map labels = new HashMap<>(); - public Relation(@NonNull final Item source, - @NonNull final Item target - ) { - this(source, target, null, null, null); - } - public Relation(@NonNull final Item source, @NonNull final Item target, final String description, From 8b6220fa19de0c59ce5d7a82b0c19a2e6e6b1e2c Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 19:24:06 +0200 Subject: [PATCH 047/310] [#565] weight label --- docs/source/inc_labels.rst | 3 ++- src/main/app/src/labels.json | 2 +- .../java/de/bonndan/nivio/model/Label.java | 4 ++- .../nivio/output/map/svg/SVGRelation.java | 21 +++++++++++---- .../nivio/output/map/svg/SVGRelationTest.java | 26 +++++++++++++++---- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index a501de5da..db79396de 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -16,4 +16,5 @@ * ``team`` Name of the responsible team (e.g. technical owner). * ``type`` The type (service, database, queue, load balancer, etc.). * ``version`` The version (e.g. software version or protocol version). -* ``visibility`` Visibility to other items. \ No newline at end of file +* ``visibility`` Visibility to other items. +* ``weight`` Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given. \ No newline at end of file diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index a38b4beab..6112a8071 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -1 +1 @@ -{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items."} \ No newline at end of file +{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items.","weight":"Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given."} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 189026bbe..3b97d1941 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -56,7 +56,9 @@ public enum Label { status("Prefix for status labels. Can be used as prefix for all other labels to mark a status for the label.", true), - condition("Prefix for condition labels.", true); + condition("Prefix for condition labels.", true), + + weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given."); /** * Separator for label key parts. diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java index 2f626a426..45f62d6a0 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java @@ -2,11 +2,14 @@ import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; import de.bonndan.nivio.model.Relation; import de.bonndan.nivio.model.RelationType; import j2html.tags.ContainerTag; import j2html.tags.DomContent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -22,6 +25,8 @@ */ class SVGRelation extends Component { + private static final Logger LOGGER = LoggerFactory.getLogger(SVGRelation.class); + public static final String MARKER_ID = "arrow"; private final HexPath hexPath; @@ -62,14 +67,22 @@ public DomContent render() { String statusColor = statusValue.getStatus().getName(); ContainerTag shadow = null; - int innerStrokeWidth = 5; + float factor = Optional.ofNullable(relation.getLabel(Label.weight)).map(s -> { + try { + return Float.parseFloat(s); + } catch (NumberFormatException e) { + LOGGER.warn("Invalid weight: {}", s); + return 1f; + } + }).orElse(1f); + int innerStrokeWidth = Math.round(5 * factor); if (statusValue.getStatus().equals(Status.UNKNOWN)) { - innerStrokeWidth = 15; + innerStrokeWidth = Math.round(15 * factor); } else { shadow = SvgTagCreator.path() .attr("d", points) .attr("stroke", statusColor) - .attr("stroke-width", 20); + .attr("stroke-width", Math.round(20 * factor)); } ContainerTag path = SvgTagCreator.path() @@ -77,8 +90,6 @@ public DomContent render() { .attr("stroke", fillId) .attr("stroke-width", innerStrokeWidth); - - if (Lifecycle.isPlanned(relation.getSource()) || Lifecycle.isPlanned(relation.getTarget())) { path.attr("stroke-dasharray", 15); } diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java index 3d3b3c31e..46d55c6de 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java @@ -27,11 +27,11 @@ class SVGRelationTest { @BeforeEach void setup() { - landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - foo = getTestItem(Group.COMMON, "foo", landscape); - bar = getTestItem(Group.COMMON, "bar", landscape); - hexpath = new HexPath(List.of(new Hex(1,2), new Hex(1,3))); - statusValue = new StatusValue("foo", Status.GREEN); + landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + foo = getTestItem(Group.COMMON, "foo", landscape); + bar = getTestItem(Group.COMMON, "bar", landscape); + hexpath = new HexPath(List.of(new Hex(1, 2), new Hex(1, 3))); + statusValue = new StatusValue("foo", Status.GREEN); } @Test @@ -107,6 +107,22 @@ public void plannedRelationIsDashed() { assertTrue(render1.contains("stroke-dasharray")); } + @Test + public void weightDeterminesStrokeWidth() { + + Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.PROVIDER); + itemRelationItem.setLabel(Label.weight, "2.44"); + + //when + SVGRelation svgRelation = new SVGRelation(hexpath, "aabbee", itemRelationItem, statusValue); + DomContent render = svgRelation.render(); + + //then + String render1 = render.render(); + var width = Math.round(5 * 2.44f); + assertThat(render1).contains("stroke-width=\"" + width + "\""); + } + @Test @DisplayName("The dataflow marker is not null") public void marker() { From 8f9d2e49e058e2e4dd81222673ebddc72e5b10bb Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 19:34:28 +0200 Subject: [PATCH 048/310] [#565] added test --- .../java/de/bonndan/nivio/model/RelationFactory.java | 10 ++++++++-- .../de/bonndan/nivio/model/RelationFactoryTest.java | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/model/RelationFactory.java b/src/main/java/de/bonndan/nivio/model/RelationFactory.java index 7d69004c1..726345f78 100644 --- a/src/main/java/de/bonndan/nivio/model/RelationFactory.java +++ b/src/main/java/de/bonndan/nivio/model/RelationFactory.java @@ -73,13 +73,16 @@ public static Relation update(@NonNull final Relation existing, Objects.requireNonNull(description); Objects.requireNonNull(landscape); - return new Relation( + Relation relation = new Relation( landscape.findOneBy(description.getSource(), existing.getSource().getGroup()), landscape.findOneBy(description.getTarget(), existing.getTarget().getGroup()), description.getDescription(), description.getFormat(), existing.getType() ); + + Labeled.merge(description, relation); + return relation; } /** @@ -98,13 +101,16 @@ public static Relation create(@NonNull final Item origin, Objects.requireNonNull(relationDescription); Objects.requireNonNull(landscape); - return new Relation( + Relation relation = new Relation( landscape.findOneBy(relationDescription.getSource(), origin.getGroup()), landscape.findOneBy(relationDescription.getTarget(), origin.getGroup()), relationDescription.getDescription(), relationDescription.getFormat(), relationDescription.getType() ); + + Labeled.merge(relationDescription, relation); + return relation; } /** diff --git a/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java index 1bd37f96c..3c5832487 100644 --- a/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java @@ -71,6 +71,7 @@ void update() { Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); Relation relation = RelationFactory.createProviderRelation(foo, bar); + relation.setLabel("foo1", "bar1"); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(foo, bar)); //landscape contains fooCopy instead of foo! @@ -78,6 +79,8 @@ void update() { RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); providerDescription.setFormat("json"); providerDescription.setDescription("huhu"); + providerDescription.setLabel("foo1", "bar2"); + providerDescription.setLabel("foo2", "bar2"); //when Relation newRelation = RelationFactory.update(relation, providerDescription, landscape); @@ -87,6 +90,8 @@ void update() { assertThat(newRelation.getTarget()).isEqualTo(bar); assertThat(newRelation.getFormat()).isEqualTo("json"); assertThat(newRelation.getDescription()).isEqualTo("huhu"); + assertThat(newRelation.getLabel("foo1")).isEqualTo("bar2"); + assertThat(newRelation.getLabel("foo2")).isEqualTo("bar2"); } @Test @@ -136,6 +141,7 @@ void create() { Item bar = ItemFactory.getTestItem("b", "bar"); landscape.setItems(Set.of(foo, bar)); RelationDescription relationDescription = RelationFactory.createProviderDescription("foo", "bar"); + relationDescription.setLabel("foo1", "bar1"); //when Relation newRelation = RelationFactory.create(foo, relationDescription, landscape); @@ -143,6 +149,7 @@ void create() { //then assertThat(newRelation.getSource()).isEqualTo(foo); assertThat(newRelation.getTarget()).isEqualTo(bar); + assertThat(newRelation.getLabel("foo1")).isEqualTo("bar1"); } @Test From 1c2ba42ab2931986a7fd927da2e38350ceb995c3 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 20:30:34 +0200 Subject: [PATCH 049/310] [#565] added test --- .../input/ComponentDescriptionValues.java | 2 +- .../nivio/input/ItemDescriptionValues.java | 10 +---- .../nivio/input/dto/ItemDescription.java | 15 +++++--- .../nivio/input/dto/RelationDescription.java | 17 ++++++++- .../java/de/bonndan/nivio/model/Labeled.java | 14 +++---- .../input/ItemDescriptionValuesTest.java | 23 ++++++++++++ .../input/dto/RelationDescriptionTest.java | 20 ++++++++++ .../de/bonndan/nivio/model/LabeledTest.java | 37 +++++++++++++++++++ 8 files changed, 115 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java index 0f31b6333..ba1f040ef 100644 --- a/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java @@ -52,7 +52,7 @@ public static void assignSafeNotNull(ComponentDescription component, ComponentDe assignSafeIfAbsent(increment.getOwner(), component.getOwner(), component::setOwner); assignSafeIfAbsent(increment.getContact(), component.getContact(), component::setContact); - Labeled.merge(increment, component); + Labeled.add(increment, component); increment.getLinks().entrySet().stream() .filter(entry -> !component.getLinks().containsKey(entry.getKey())) diff --git a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java index c6df223a2..02b1fc1c7 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java @@ -31,15 +31,7 @@ public static void assignNotNull(ItemDescription existing, ItemDescription incre if (increment.getAddress() != null) existing.setAddress(increment.getAddress()); - increment.getRelations().forEach(relationDescription -> { - RelationDescription rel = relationDescription.findMatching(existing.getRelations()) - .map(relationDescription1 -> { - relationDescription1.merge(relationDescription); - return relationDescription1; - }) - .orElse(relationDescription); - existing.addOrReplaceRelation(rel); - }); + increment.getRelations().forEach(existing::addOrReplaceRelation); assignSafe(increment.getInterfaces(), (set) -> set.forEach(intf -> existing.getInterfaces().add(intf))); } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index 9b48d7718..2bf0426e5 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -240,13 +240,18 @@ public void setRelations(List relations) { /** * Add or update a relation description. * - * If an equal relation description exist, it is replaced by the newer one. + * If an equal relation description exist, it is updated with values from the newer one. * - * @param relationItem relation dto to be added + * @param description relation dto to be added */ - public void addOrReplaceRelation(@NonNull final RelationDescription relationItem) { - Objects.requireNonNull(relationItem).findMatching(this.relations).ifPresent(this.relations::remove); - this.relations.add(relationItem); + public void addOrReplaceRelation(@NonNull final RelationDescription description) { + RelationDescription relationDescription = Objects.requireNonNull(description).findMatching(this.relations) + .map(relationDescription1 -> { + relationDescription1.update(description); + return relationDescription1; + }) + .orElse(description); + this.relations.add(relationDescription); } public String getAddress() { diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 22735af3f..209207990 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input.dto; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.model.Relation; import de.bonndan.nivio.model.RelationType; import de.bonndan.nivio.search.ItemMatcher; import io.swagger.v3.oas.annotations.media.Schema; @@ -113,7 +114,7 @@ public void setLabel(String key, String value) { * @param relations a collection of existing relations * @return the sibling */ - public Optional findMatching(@NonNull final Collection relations) { + Optional findMatching(@NonNull final Collection relations) { return Objects.requireNonNull(relations).stream() .filter(rel -> matches(source, rel.getSource())) .filter(rel -> matches(target, rel.getTarget())) @@ -125,4 +126,18 @@ private boolean matches(String end1, String end2) { Optional m2 = ItemMatcher.forTarget(end2); return m1.isPresent() && m2.isPresent() && m1.map(m -> m.equals(m2.get())).orElse(false); } + + /** + * Updates the current object with values from the param. + * + * @param newer update + */ + public void update(@NonNull final RelationDescription newer) { + Objects.requireNonNull(newer); + + setDescription(newer.description); + setFormat(newer.format); + + Labeled.merge(newer, this); + } } diff --git a/src/main/java/de/bonndan/nivio/model/Labeled.java b/src/main/java/de/bonndan/nivio/model/Labeled.java index 392d98ebe..75a348321 100644 --- a/src/main/java/de/bonndan/nivio/model/Labeled.java +++ b/src/main/java/de/bonndan/nivio/model/Labeled.java @@ -205,12 +205,12 @@ default Map> indexedByPrefix(String prefix) { } /** - * Copies all non-null labels from source to target. + * ADd all non-null labels from source to target where target labels are not set. * * @param source label source * @param target target */ - static void merge(@NonNull final Labeled source, @NonNull final Labeled target) { + static void add(@NonNull final Labeled source, @NonNull final Labeled target) { source.getLabels().entrySet().stream() .filter(entry -> entry.getValue() != null) .filter(entry -> target.getLabel(entry.getKey()) == null) @@ -218,15 +218,15 @@ static void merge(@NonNull final Labeled source, @NonNull final Labeled target) } /** - * Copies all non-null labels from source. + * Copies all non-null value labels from source to target. * * @param source label source + * @param target target */ - default void merge(@NonNull final Labeled source) { - Objects.requireNonNull(source).getLabels().entrySet().stream() + static void merge(@NonNull final Labeled source, @NonNull final Labeled target) { + source.getLabels().entrySet().stream() .filter(entry -> entry.getValue() != null) - .filter(entry -> getLabel(entry.getKey()) == null) - .forEach(entry -> setLabel(entry.getKey(), entry.getValue())); + .forEach(entry -> target.setLabel(entry.getKey(), entry.getValue())); } /** diff --git a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java index 54133fe49..9ca2e2267 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java @@ -92,6 +92,29 @@ public void incrementAddsDataflow() { assertEquals(2, sd1.getRelations().size()); } + @Test + public void incrementUpdatesRelationDescription() { + + ItemDescription sd1 = new ItemDescription(); + sd1.setIdentifier("sd1"); + RelationDescription other = RelationFactory.createDataflowDescription(sd1, "other"); + sd1.addOrReplaceRelation(other); + + ItemDescription increment = new ItemDescription(); + increment.setIdentifier("sd1"); + RelationDescription another = RelationFactory.createDataflowDescription(increment, "other"); + another.setLabel("foo", "bar"); + increment.addOrReplaceRelation(another); + + //when + ItemDescriptionValues.assignNotNull(sd1, increment); + + + assertEquals(1, sd1.getRelations().size()); + RelationDescription relationDescription = sd1.getRelations().iterator().next(); + assertEquals("bar", relationDescription.getLabel("foo")); + } + @Test public void incrementAddsNetworks() { diff --git a/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java index 286f5fc8b..c48098aa1 100644 --- a/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java +++ b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java @@ -51,4 +51,24 @@ void findMatchingOtherTarget() { assertThat(matching).isEmpty(); } + @Test + void update() { + var rel = new RelationDescription("aGroup/foo", "bGroup/notBar"); + rel.setLabel("foo", "one"); + rel.setFormat("f1"); + + var newer = new RelationDescription("aGroup/foo", "bGroup/notBar"); + newer.setDescription("one"); + newer.setFormat("foo"); + newer.setLabel("foo", "two"); + + //when + rel.update(newer); + + //then + assertThat(rel.getDescription()).isEqualTo("one"); + assertThat(rel.getFormat()).isEqualTo("foo"); + assertThat(rel.getLabel("foo")).isEqualTo("two"); + } + } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/LabeledTest.java b/src/test/java/de/bonndan/nivio/model/LabeledTest.java index 30594f781..56a58b71d 100644 --- a/src/test/java/de/bonndan/nivio/model/LabeledTest.java +++ b/src/test/java/de/bonndan/nivio/model/LabeledTest.java @@ -131,4 +131,41 @@ void anySetterAcceptsNumber() { //then assertThat(i.getLabel("foo")).isEqualTo("1"); } + + @Test + void merge() { + ItemDescription i = new ItemDescription(); + i.setLabel("foo1", 1L); + i.setLabel("foo2", 1L); + ItemDescription target = new ItemDescription(); + i.setLabel("foo1", 2L); + i.setLabel("bar", 2L); + + //when + Labeled.merge(i, target); + + //then + assertThat(target.getLabel("foo1")).isEqualTo("2"); + assertThat(target.getLabel("foo2")).isEqualTo("1"); + assertThat(target.getLabel("bar")).isEqualTo("2"); + } + + @Test + void add() { + ItemDescription i = new ItemDescription(); + i.setLabel("foo1", "after"); + i.setLabel("foo2", 1L); + + ItemDescription target = new ItemDescription(); + i.setLabel("foo1", "before"); + i.setLabel("bar", 2L); + + //when + Labeled.add(i, target); + + //then + assertThat(target.getLabel("foo1")).isEqualTo("before"); + assertThat(target.getLabel("foo2")).isEqualTo("1"); + assertThat(target.getLabel("bar")).isEqualTo("2"); + } } \ No newline at end of file From 5a19279fa2461b3e19bb8f3cc41577b73bdce588 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 21:44:28 +0200 Subject: [PATCH 050/310] [#565] showing relation labels in frontend --- .../Landscape/Map/MapRelation/MapRelation.tsx | 10 ++++++++++ src/main/app/src/Components/Landscape/Utils/utils.tsx | 4 ++-- src/main/app/src/interfaces.ts | 1 + .../bonndan/nivio/input/dto/RelationDescription.java | 2 ++ src/main/java/de/bonndan/nivio/model/Relation.java | 4 +++- .../resources/example/services/pet_clinic_billing.yml | 2 ++ 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx b/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx index 85949a78f..d15e3882c 100644 --- a/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx +++ b/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx @@ -9,6 +9,7 @@ import componentStyles from '../../../../Resources/styling/ComponentStyles'; import ItemAvatar from '../../Modals/Item/ItemAvatar'; import { Close, HelpRounded } from '@material-ui/icons'; import { LandscapeContext } from '../../../../Context/LandscapeContext'; +import { getLabels } from "../../Utils/utils"; interface Props { source: IItem; @@ -32,6 +33,8 @@ const MapRelation: React.FC = ({ source, target, relation }) => { const sourceTitle = source.name || source.identifier; const targetTitle = target.name || target.identifier; const title = sourceTitle + ' to ' + targetTitle; + const labels = relation ? getLabels(relation) : null; + const sourceStatus = landscapeContext.getAssessmentSummary(source.fullyQualifiedIdentifier); const targetStatus = landscapeContext.getAssessmentSummary(target.fullyQualifiedIdentifier); @@ -81,6 +84,13 @@ const MapRelation: React.FC = ({ source, target, relation }) => {
+ {labels ? ( + <> + Labels + {labels} + + ) : null} +
Source

{ return links; }; -export const getLabels = (element: IGroup | IItem) => { +export const getLabels = (element: IGroup | IItem | IRelation ) => { let labels: ReactElement[] = []; if (!element?.labels) { return null; diff --git a/src/main/app/src/interfaces.ts b/src/main/app/src/interfaces.ts index da85809aa..3b1523266 100644 --- a/src/main/app/src/interfaces.ts +++ b/src/main/app/src/interfaces.ts @@ -133,6 +133,7 @@ export interface IRelation { name: string; id: string; direction: string; + labels: ILabels; } export interface ILabels { diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 209207990..bb05bab7a 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.dto; +import com.fasterxml.jackson.annotation.JsonAnySetter; import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.Relation; import de.bonndan.nivio.model.RelationType; @@ -104,6 +105,7 @@ public Map getLabels() { } @Override + @JsonAnySetter public void setLabel(String key, String value) { getLabels().put(key, value); } diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index 0cb827451..bb556b270 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -110,7 +110,6 @@ public Map getLabels() { } @Override - @JsonAnySetter public void setLabel(String key, String value) { labels.put(key, value); } @@ -154,6 +153,8 @@ static class ApiModel { public final String direction; + public final Map labels; + ApiModel(@NonNull final Relation relation, @NonNull final Item owner) { source = relation.source; target = relation.target; @@ -161,6 +162,7 @@ static class ApiModel { format = relation.format; type = relation.type; id = relation.getIdentifier(); + labels = relation.getLabels(); if (relation.source.equals(owner)) { name = StringUtils.isEmpty(target.getName()) ? target.getIdentifier() : target.getName(); diff --git a/src/test/resources/example/services/pet_clinic_billing.yml b/src/test/resources/example/services/pet_clinic_billing.yml index abedbf484..ae50a2aea 100644 --- a/src/test/resources/example/services/pet_clinic_billing.yml +++ b/src/test/resources/example/services/pet_clinic_billing.yml @@ -23,6 +23,8 @@ items: relations: - type: dataflow target: emailer + description: Sends PDF invoices to customers + weight: 2.3 tags: - java - backend From c84237a117a6a62e7ade63ae701e5481eca29a9c Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 21:46:54 +0200 Subject: [PATCH 051/310] [#565] max relation weight 5 --- src/main/java/de/bonndan/nivio/model/Label.java | 2 +- .../java/de/bonndan/nivio/output/map/svg/SVGRelation.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 3b97d1941..8b0b0da2b 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -58,7 +58,7 @@ public enum Label { condition("Prefix for condition labels.", true), - weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given."); + weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."); /** * Separator for label key parts. diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java index 45f62d6a0..18afa8a31 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java @@ -69,7 +69,11 @@ public DomContent render() { ContainerTag shadow = null; float factor = Optional.ofNullable(relation.getLabel(Label.weight)).map(s -> { try { - return Float.parseFloat(s); + float v = Float.parseFloat(s); + if (v > 5f) { + v = 5; + } + return v; } catch (NumberFormatException e) { LOGGER.warn("Invalid weight: {}", s); return 1f; From 42360de62dd00b5f3a95230775bf0f68c729110d Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Thu, 24 Jun 2021 22:00:26 +0200 Subject: [PATCH 052/310] [#565] doc cleanup --- docs/source/inc_labels.rst | 2 +- src/main/app/src/labels.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index db79396de..1513928c8 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -17,4 +17,4 @@ * ``type`` The type (service, database, queue, load balancer, etc.). * ``version`` The version (e.g. software version or protocol version). * ``visibility`` Visibility to other items. -* ``weight`` Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given. \ No newline at end of file +* ``weight`` Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given. \ No newline at end of file diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index 6112a8071..9c419ae66 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -1 +1 @@ -{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items.","weight":"Importance or relations. Used as factor for drawn width if numbers between 0 and 3 are given."} \ No newline at end of file +{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items.","weight":"Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."} \ No newline at end of file From 6e4d7549ed6891e0975221734cae5ddaa339ce84 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 28 Jun 2021 12:15:06 +0200 Subject: [PATCH 053/310] Changed K8s scanning --- docs/source/schema/Models/ItemDescription.rst | 4 +- .../schema/Models/LandscapeDescription.rst | 10 +- docs/source/schema/spec.json | 92 +++++++------- .../java/de/bonndan/nivio/input/ItemType.java | 3 + .../java/de/bonndan/nivio/input/Seed.java | 2 +- .../nivio/input/demo/ChangeTrigger.java | 14 +- .../nivio/input/dto/RelationDescription.java | 3 +- .../input/kubernetes/DeploymentItem.java | 24 ++++ .../InputFormatHandlerKubernetes.java | 120 +++++++++++++++--- .../bonndan/nivio/input/kubernetes/Item.java | 71 +++++++++++ .../nivio/input/kubernetes/PodItem.java | 21 +++ .../input/kubernetes/ReplicaSetItem.java | 34 +++++ .../nivio/input/kubernetes/ServiceItem.java | 21 +++ .../input/kubernetes/StatefulSetItem.java | 21 +++ .../java/de/bonndan/nivio/model/Item.java | 4 +- .../java/de/bonndan/nivio/model/Relation.java | 2 +- .../nivio/output/icons/IconMapping.java | 10 +- .../bonndan/nivio/input/KubernetesTest.java | 3 +- .../nivio/input/demo/ChangeTriggerTest.java | 4 +- src/test/resources/example/example_k8s.yml | 2 +- 20 files changed, 379 insertions(+), 86 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/Item.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..022f72838 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -83,12 +83,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The lifecycle state of an item. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..dd41a02f8 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -73,16 +73,16 @@ LandscapeDescription - - optional, defaults to null - null - * - items - - List - - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - - optional, defaults to null - - null * - partial - Boolean - marks that the landscape is not complete, but an update - optional, defaults to null - null + * - items + - List + - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. + - optional, defaults to null + - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 4033798f9..09b18fb47 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -172,24 +172,24 @@ "$ref" : "#/components/schemas/InterfaceDescription" } }, - "providedBy" : { - "type" : "array", - "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", - "example" : "shipping-mysqldb", - "items" : { - "type" : "string", - "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", - "example" : "shipping-mysqldb" + "providedBy": { + "type": "array", + "description": "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", + "example": "shipping-mysqldb", + "items": { + "type": "string", + "description": "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", + "example": "shipping-mysqldb" } }, - "icon" : { - "type" : "string", - "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." + "icon": { + "type": "string", + "description": "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." }, - "color" : { - "type" : "string", - "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", - "example" : "4400FF" + "color": { + "type": "string", + "description": "Overrides the group color. Use an HTML hex color code without the leading hash.", + "example": "4400FF" }, "address": { "type": "string", @@ -213,7 +213,7 @@ "EOL" ] }, - "status": { + "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -226,7 +226,7 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "statuses": { + "status": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -391,23 +391,23 @@ "$ref" : "#/components/schemas/SourceReference" } }, - "config" : { - "$ref" : "#/components/schemas/LandscapeConfig" + "config": { + "$ref": "#/components/schemas/LandscapeConfig" }, - "groups" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/GroupDescription" + "groups": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/GroupDescription" }, - "description" : "Description of item groups (optional, can also be given in sources)." + "description": "Description of item groups (optional, can also be given in sources)." }, - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Additional labels for the landscape." + "labels": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Additional labels for the landscape." }, - "description" : "Additional labels for the landscape." + "description": "Additional labels for the landscape." }, "color": { "type": "string" @@ -415,25 +415,25 @@ "icon": { "type": "string" }, - "items" : { - "type" : "array", - "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/ItemDescription" - } + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" }, - "partial" : { - "type" : "boolean", - "description" : "marks that the landscape is not complete, but an update" + "items": { + "type": "array", + "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", + "writeOnly": true, + "items": { + "$ref": "#/components/schemas/ItemDescription" + } }, - "links" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" + "links": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Link" }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example": "github: https://github.com/dedica-team/nivio" } } }, diff --git a/src/main/java/de/bonndan/nivio/input/ItemType.java b/src/main/java/de/bonndan/nivio/input/ItemType.java index 4868ed3ab..c00c48a3a 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemType.java +++ b/src/main/java/de/bonndan/nivio/input/ItemType.java @@ -12,4 +12,7 @@ public class ItemType { public static final String POD = "pod"; public static final String DATABASE = "database"; public static final String KEYVALUESTORE = "keyvaluestore"; + public static final String DEPLOYMENT = "deployment"; + public static final String REPLICASET = "replicaset"; + public static final String STATEFULSET = "statefulset"; } diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index cadc889b2..63f0884c4 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -70,7 +70,7 @@ public List getDemoFiles() { Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { - demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); + demoFiles.add(new File(absPath + "/src/test/resources/example/example_k8s.yml").toURI().toURL()); if (value.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); diff --git a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java index a8f1e71f0..2dace84be 100644 --- a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java +++ b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java @@ -1,9 +1,9 @@ package de.bonndan.nivio.input.demo; -import de.bonndan.nivio.config.ConfigurableEnvVars; import de.bonndan.nivio.input.IndexEvent; import de.bonndan.nivio.input.LandscapeDescriptionFactory; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.model.LandscapeRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; @@ -13,6 +13,7 @@ import java.io.File; import java.nio.file.Paths; import java.util.Optional; +import java.util.stream.StreamSupport; @Component public class ChangeTrigger { @@ -20,19 +21,22 @@ public class ChangeTrigger { private static final Logger LOGGER = LoggerFactory.getLogger(ChangeTrigger.class); private final LandscapeDescriptionFactory landscapeDescriptionFactory; + private final LandscapeRepository landscapeRepository; private final ApplicationEventPublisher eventPublisher; - public ChangeTrigger(LandscapeDescriptionFactory landscapeDescriptionFactory, - ApplicationEventPublisher eventPublisher + public ChangeTrigger( + LandscapeRepository landscapeRepository, + LandscapeDescriptionFactory landscapeDescriptionFactory, + ApplicationEventPublisher eventPublisher ) { this.landscapeDescriptionFactory = landscapeDescriptionFactory; + this.landscapeRepository = landscapeRepository; this.eventPublisher = eventPublisher; } @Scheduled(initialDelay = 20000, fixedDelay = 30000) public void trigger() { - - if (ConfigurableEnvVars.DEMO.value().isEmpty()) { + if (StreamSupport.stream(landscapeRepository.findAll().spliterator(), false).noneMatch(landscape -> landscape.getIdentifier().equals("petclinic"))) { LOGGER.debug("DEMO not set, not simulating any pet clinic events."); return; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 47198a9bb..8cc99e0a1 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -21,7 +21,8 @@ public class RelationDescription { @Schema(description = "The item identifier of the target. Prepend a group identifier if the simple item identifier is ambiguous.", example = "dataSink|groupB/dataSink") private String target; - public RelationDescription(){} + public RelationDescription() { + } public RelationDescription(String source, String target) { this.source = source; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java new file mode 100644 index 000000000..41afc6fde --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -0,0 +1,24 @@ +package de.bonndan.nivio.input.kubernetes; + + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.Deployment; + +public class DeploymentItem extends Item { + private Deployment deployment; + + public void setDeployment(Deployment deployment) { + this.deployment = deployment; + } + + public Deployment getDeployment() { + return deployment; + } + + @Override + public HasMetadata getWrappedItem() { + return deployment; + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index e20ea45b8..324836940 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -1,8 +1,8 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.InputFormatHandler; import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; @@ -90,12 +90,113 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti }); List services = client.services().list().getItems(); + List itemServices = new ArrayList<>(); LOGGER.info("Found services: {}", services.stream().map(service -> service.getMetadata().getName()).collect(Collectors.toList())); services.stream() .filter(service -> namespace == null || namespace.equals(service.getMetadata().getNamespace())) - .forEach(service -> descriptions.add(createDescriptionFromService(service, pods))); + .forEach(service -> itemServices.add(createDescriptionFromService(service, pods))); + + descriptions.addAll(itemServices); + //landscapeDescription.mergeItems(descriptions); + + var deployments = getDeployments(client); + var replicaSets = getReplicaSets(client); + var podList = getPodItems(); + var serviceList = getServiceItems(client); + var statefulSets = getStatefulSet(client); + + var itemList = new ArrayList(); + itemList.addAll(deployments); + itemList.addAll(replicaSets); + itemList.addAll(podList); + itemList.addAll(serviceList); + itemList.addAll(statefulSets); + crossReferenceOwner(itemList); + var e = createItemDescription(itemList); + landscapeDescription.mergeItems(e); + } + + private List createItemDescription(List itemList) { + return itemList.stream().map(item -> { + var itemDescription = new ItemDescription(); + itemDescription.setIdentifier(item.getUid()); + itemDescription.setName(item.getName()); + itemDescription.setType(item.getType()); + if (!item.getOwner().isEmpty()) { + itemDescription.setOwner(item.getOwner().get(0).getName()); + } + itemDescription.setGroup(item.getGroup()); + item.getOwner().forEach(owner -> itemDescription.addRelation(new RelationDescription(owner.getUid(), item.getUid()))); + return itemDescription; + }).collect(Collectors.toList()); + } + + private void crossReferenceOwner(ArrayList items) { + items.forEach(item -> { + var owners = new ArrayList(); + owners = (ArrayList) items.stream().filter(item1 -> item.getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(item1.getUid())).collect(Collectors.toList()); + item.setOwners(owners); + }); + } + + private List getPodItems() { + var pods = getPods(); + return pods.stream().map(pod -> { + var podItem = new PodItem(); + podItem.setType(ItemType.POD); + podItem.setPod(pod); + podItem.setName(pod.getMetadata().getName()); + podItem.setUid(pod.getMetadata().getUid()); + return podItem; + }).collect(Collectors.toList()); + } - landscapeDescription.mergeItems(descriptions); + private List getDeployments(KubernetesClient client) { + var deploymentList = client.apps().deployments().list().getItems(); + return deploymentList.stream().map(deployment -> { + var deploymentItem = new DeploymentItem(); + deploymentItem.setType(ItemType.DEPLOYMENT); + deploymentItem.setDeployment(deployment); + deploymentItem.setName(deployment.getMetadata().getName()); + deploymentItem.setUid(deployment.getMetadata().getUid()); + return deploymentItem; + }).collect(Collectors.toList()); + } + + private List getReplicaSets(KubernetesClient client) { + var replicaSetList = client.apps().replicaSets().list().getItems(); + return replicaSetList.stream().map(replicaSet -> { + var replicaSetItem = new ReplicaSetItem(); + replicaSetItem.setType(ItemType.REPLICASET); + replicaSetItem.setReplicaSet(replicaSet); + replicaSetItem.setName(replicaSet.getMetadata().getName()); + replicaSetItem.setUid(replicaSet.getMetadata().getUid()); + return replicaSetItem; + }).collect(Collectors.toList()); + } + + private List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> { + var serviceItem = new ServiceItem(); + serviceItem.setType(ItemType.SERVICE); + serviceItem.setService(service); + serviceItem.setName(service.getMetadata().getName()); + serviceItem.setUid(service.getMetadata().getUid()); + return serviceItem; + }).collect(Collectors.toList()); + } + + private List getStatefulSet(KubernetesClient client) { + var statefulSetList = client.apps().statefulSets().list().getItems(); + return statefulSetList.stream().map(statefulSet -> { + var statefulSetItem = new StatefulSetItem(); + statefulSetItem.setType(ItemType.STATEFULSET); + statefulSetItem.setStatefulSet(statefulSet); + statefulSetItem.setName(statefulSet.getMetadata().getName()); + statefulSetItem.setUid(statefulSet.getMetadata().getUid()); + return statefulSetItem; + }).collect(Collectors.toList()); } @Override @@ -138,22 +239,11 @@ private ItemDescription createDescriptionFromService(Service kubernetesService, ItemDescription service = new ItemDescription(); service.setIdentifier(kubernetesService.getMetadata().getName()); - service.setType(kubernetesService.getSpec().getType()); + service.setType(ItemType.SERVICE); String group = getGroup(kubernetesService); service.setGroup(group); - String targetId = ""; - Map selector = kubernetesService.getSpec().getSelector(); - if (selector != null) { - targetId = selector.getOrDefault(APP_SELECTOR, null); - } - - //TODO, check if this is reliable - if (!StringUtils.isEmpty(targetId)) { - service.addRelation(new RelationDescription(service.getIdentifier(), targetId)); - } - //link pods as providers pods.stream() .filter(pod -> pod.getName().startsWith(service.getIdentifier())) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java new file mode 100644 index 000000000..d2cf5b79b --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -0,0 +1,71 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.HasMetadata; + +import java.util.ArrayList; +import java.util.List; + +public abstract class Item { + protected String name; + private String uid; + private String type; + + private final List owners = new ArrayList<>(); + + private final List relationDescriptionList = new ArrayList<>(); + + public List getRelationDescriptionList() { + return relationDescriptionList; + } + + public abstract HasMetadata getWrappedItem(); + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public String getGroup() { + if (this.getOwner().isEmpty()) { + return name; + } else { + return this.getOwner().get(0).getGroup(); + } + } + + public void setName(String name) { + this.name = name; + } + + public List getOwner() { + return owners; + } + + public void addOwner(Item owner) { + this.owners.add(owner); + } + + public void setOwners(List owners) { + this.owners.addAll(owners); + } + + public void addRelation(RelationDescription relationDescription) { + relationDescriptionList.add(relationDescription); + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java new file mode 100644 index 000000000..976dd4fcf --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Pod; + +public class PodItem extends Item { + Pod pod; + + public Pod getPod() { + return pod; + } + + public void setPod(Pod pod) { + this.pod = pod; + } + + @Override + public HasMetadata getWrappedItem() { + return pod; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java new file mode 100644 index 000000000..b5f926be2 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -0,0 +1,34 @@ +package de.bonndan.nivio.input.kubernetes; + + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.ReplicaSet; + +import java.util.List; + +public class ReplicaSetItem extends Item { + ReplicaSet replicaSet; + List serviceItems; + + + public ReplicaSet getReplicaSet() { + return replicaSet; + } + + public void setReplicaSet(ReplicaSet replicaSet) { + this.replicaSet = replicaSet; + } + + public List getServiceItems() { + return serviceItems; + } + + public void setServiceItems(List serviceItems) { + this.serviceItems = serviceItems; + } + + @Override + public HasMetadata getWrappedItem() { + return replicaSet; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java new file mode 100644 index 000000000..d937ef094 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Service; + +public class ServiceItem extends Item { + Service service; + + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + @Override + public HasMetadata getWrappedItem() { + return service; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java new file mode 100644 index 000000000..2eb5101f5 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; + +public class StatefulSetItem extends Item { + private StatefulSet statefulSet; + + public StatefulSet getStatefulSet() { + return statefulSet; + } + + public void setStatefulSet(StatefulSet statefulSet) { + this.statefulSet = statefulSet; + } + + @Override + public HasMetadata getWrappedItem() { + return statefulSet; + } +} diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 9f8583c87..0e72b57f5 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -178,7 +178,7 @@ public Set getRelations() { /** * Adds a relation or replaces the similar one. - * + *

* This is necessary because {@link Set} does not replace AND we need to check relation end equality on object level * because referenced source or target items will be replaced by new copies. * @@ -186,7 +186,7 @@ public Set getRelations() { */ public void addOrReplace(@NonNull final Relation relation) { if (relation.getSource() != this && relation.getTarget() != this) { - throw new IllegalArgumentException("Relation contains no reference to item."); + //throw new IllegalArgumentException(String.format("Relation contains no reference to item.%s %s", relation.getIdentifier(), this)); } getSimilar(relation).map(relations::remove); diff --git a/src/main/java/de/bonndan/nivio/model/Relation.java b/src/main/java/de/bonndan/nivio/model/Relation.java index aa8ba3d67..4356c8069 100644 --- a/src/main/java/de/bonndan/nivio/model/Relation.java +++ b/src/main/java/de/bonndan/nivio/model/Relation.java @@ -54,7 +54,7 @@ public Relation(@NonNull final Item source, } if (source.equals(target)) { - throw new IllegalArgumentException("Relation source and target are equal."); + throw new IllegalArgumentException(String.format("Relation source and target are equal.%s %s", source, target)); } this.source = source; diff --git a/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java b/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java index ac8c63c72..286a7fe66 100644 --- a/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java +++ b/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java @@ -14,6 +14,8 @@ public enum IconMapping { BACKEND("application-cog"), CACHE("flash-circle"), CONTAINER("inbox"), + DEPLOYMENT("rocket-launch"), + POD("application"), FIREWALL("wall"), FRONTEND("television-guide"), HUMANUSER("account"), @@ -22,10 +24,12 @@ public enum IconMapping { LOADBALANCER("call-split"), MESSAGEQUEUE("tray-full"), MOBILECLIENT("cellphone"), - SERVICE("application-cog"), + REPLICASET("content-copy"), + SERVICE("information-outline"), + SECRET("application-cog"), + STATEFULSET("harddisk-plus"), VOLUME("harddisk"), - WEBSERVICE("application"), - ; + WEBSERVICE("application"); private final String icon; diff --git a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/KubernetesTest.java index 5f0aa2ef9..6a99eb04c 100644 --- a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/KubernetesTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -21,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@EnableKubernetesMockClient(crud = true) +@EnableKubernetesMockClient(crud = true, https = false) public class KubernetesTest { static KubernetesClient client; diff --git a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java index 242fa9dec..05a78df4b 100644 --- a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java +++ b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java @@ -1,11 +1,11 @@ package de.bonndan.nivio.input.demo; import de.bonndan.nivio.input.LandscapeDescriptionFactory; +import de.bonndan.nivio.model.LandscapeRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationEventPublisher; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class ChangeTriggerTest { @@ -18,7 +18,7 @@ class ChangeTriggerTest { void setUp() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - trigger = new ChangeTrigger(factory, publisher); + trigger = new ChangeTrigger(new LandscapeRepository(), factory, publisher); } @Test diff --git a/src/test/resources/example/example_k8s.yml b/src/test/resources/example/example_k8s.yml index e091a4676..c63389f6d 100644 --- a/src/test/resources/example/example_k8s.yml +++ b/src/test/resources/example/example_k8s.yml @@ -2,7 +2,7 @@ identifier: k8s:example name: Kubernetes example sources: - format: kubernetes - url: http://192.168.99.100:8080?namespace=default&groupLabel=release + url: http://10.96.0.1:8443?namespace=default&groupLabel=release config: kpis: From 1a4d283a015e1718e5005a0673a9e4c4120abe02 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 28 Jun 2021 17:00:37 +0200 Subject: [PATCH 054/310] Changed K8s scanning --- .../kubernetes/InputFormatHandlerKubernetes.java | 4 ++++ .../java/de/bonndan/nivio/input/kubernetes/Item.java | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 324836940..2ddd0c0c8 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -127,6 +127,9 @@ private List createItemDescription(List itemList) { } itemDescription.setGroup(item.getGroup()); item.getOwner().forEach(owner -> itemDescription.addRelation(new RelationDescription(owner.getUid(), item.getUid()))); + if (!item.getStatus().isEmpty()) { + item.getStatus().forEach((k, v) -> itemDescription.setLabel(Label.condition.withPrefix(k), v)); + } return itemDescription; }).collect(Collectors.toList()); } @@ -159,6 +162,7 @@ private List getDeployments(KubernetesClient client) { deploymentItem.setDeployment(deployment); deploymentItem.setName(deployment.getMetadata().getName()); deploymentItem.setUid(deployment.getMetadata().getUid()); + deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); return deploymentItem; }).collect(Collectors.toList()); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java index d2cf5b79b..ed8781f0f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -4,13 +4,17 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class Item { protected String name; private String uid; private String type; + private final Map status = new HashMap<>(); + private final List owners = new ArrayList<>(); private final List relationDescriptionList = new ArrayList<>(); @@ -19,6 +23,14 @@ public List getRelationDescriptionList() { return relationDescriptionList; } + public Map getStatus() { + return status; + } + + public void addStatus(String key, String value) { + status.put(key, value); + } + public abstract HasMetadata getWrappedItem(); public String getType() { From 8f2116dd4600f00cc994cf2bcba62831140006b4 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Wed, 30 Jun 2021 10:50:28 +0200 Subject: [PATCH 055/310] modify the methods getGitHub() and checkAnyEnv() --- .../input/external/github/GitHubConfig.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java index 7ae410b20..367ac1ff6 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubConfig.java @@ -7,6 +7,7 @@ import org.springframework.util.StringUtils; import java.io.IOException; +import java.util.Properties; @Configuration public class GitHubConfig { @@ -45,16 +46,21 @@ public GitHub getGitHub() { } try { - return GitHubBuilder.fromEnvironment().build(); + Properties properties = new Properties(); + properties.setProperty("login",gitHubProperties.getLogin()); + properties.setProperty("password",gitHubProperties.getPassword()); + properties.setProperty("oauth",gitHubProperties.getOauth()); + properties.setProperty("jwt",gitHubProperties.getJwt()); + return GitHubBuilder.fromProperties(properties).build(); } catch (IOException ignored) { return null; } } private boolean checkAnyEnv() { - return !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getLogin())")) || - !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getPassword()")) || - !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getOauth()")) || - !StringUtils.isEmpty(System.getenv("Optional.ofNullable(gitHubProperties.getJwt()")); + return !StringUtils.isEmpty(System.getenv(gitHubProperties.getLogin())) || + !StringUtils.isEmpty(System.getenv(gitHubProperties.getPassword())) || + !StringUtils.isEmpty(System.getenv(gitHubProperties.getOauth())) || + !StringUtils.isEmpty(System.getenv(gitHubProperties.getJwt())); } } From 87d3ba0bc12c02bd06758d6539478745734369be Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 1 Jul 2021 12:26:25 +0200 Subject: [PATCH 056/310] add new variable --- .../bonndan/nivio/input/external/GitLabRepoHandlerTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java b/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java index 66fcca9bd..1bbe730ac 100644 --- a/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java @@ -3,6 +3,7 @@ import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.external.github.GitHubRepoHandler; import de.bonndan.nivio.input.external.gitlab.GitLabConfig; +import de.bonndan.nivio.input.external.gitlab.GitLabProperties; import de.bonndan.nivio.input.external.gitlab.GitLabRepoHandler; import de.bonndan.nivio.model.Link; import org.gitlab4j.api.*; @@ -99,7 +100,8 @@ void setsDescriptionIfEmpty() throws IOException, ExecutionException, Interrupte void integration() throws IOException, ExecutionException, InterruptedException { //env vars used, configure them properly - GitLabConfig gitLabConfig = new GitLabConfig(); + GitLabProperties gitLabProperties = new GitLabProperties(); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); GitLabApi gitLabAPI = gitLabConfig.getGitLabAPI(); handler = new GitLabRepoHandler(gitLabAPI); From c389615dfee0a3fbef70c2c0c114b04003c095e2 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sun, 4 Jul 2021 18:59:45 +0200 Subject: [PATCH 057/310] version bump for next release --- pom.xml | 2 +- src/main/app/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a8a098c59..bc2dd90aa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ de.bonndan nivio - 0.4.0 + 0.4.1 org.springframework.boot diff --git a/src/main/app/package.json b/src/main/app/package.json index 7d113ed5e..caa5803da 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -1,6 +1,6 @@ { "name": "nivio", - "version": "0.4.0", + "version": "0.4.1", "private": true, "homepage": "./", "dependencies": { From d1e2e05ad05c15628ffe9c46989403f402c84b05 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 5 Jul 2021 09:50:13 +0200 Subject: [PATCH 058/310] modify the method returnsNullIfNoConfig() --- .../nivio/input/external/github/GitHubConfigTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java index 10c22ab93..cfa1b8c1b 100644 --- a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java @@ -8,10 +8,12 @@ class GitHubConfigTest { @Test void returnsNullIfNoConfig() { - GitHubProperties gitHubProperties = null; - GitHubConfig gitHubConfig = new GitHubConfig(null); + + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + GitHubConfig gitHubConfig = new GitHubConfig(gitHubProperties); assertNull(gitHubConfig.getGitHub()); } + @Test void groupedAssertions(){ GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); From b5067068d3541ca9fa8916765e9c9b19665028c4 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 5 Jul 2021 12:12:50 +0200 Subject: [PATCH 059/310] add the seed properties --- .../bonndan/nivio/config/NivioConfigProperties.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java index a7ad634cb..dd0cbcd28 100644 --- a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java +++ b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java @@ -40,6 +40,7 @@ public class NivioConfigProperties { private String brandingMessage; //iconFolder: /a/local/path + private String seed; public String getBaseUrl() { return baseUrl; @@ -105,13 +106,17 @@ public void setBrandingMessage(String brandingMessage) { this.brandingMessage = brandingMessage; } + public String getSeed(){ return seed; } + + public void setSeed(String seed){ this.seed = seed;} + public ApiModel getApiModel() { java.net.URL brandingLogoUrl = null; try { brandingLogoUrl = this.brandingLogoUrl != null ? new java.net.URL(getBrandingLogoUrl()) : null; } catch (MalformedURLException ignored) { } - return new ApiModel(baseUrl, version, brandingForeground, brandingBackground, brandingSecondary, brandingLogoUrl, brandingMessage); + return new ApiModel(baseUrl, version, brandingForeground, brandingBackground, brandingSecondary, brandingLogoUrl, brandingMessage,seed); } @JsonInclude(JsonInclude.Include.NON_NULL) @@ -123,6 +128,7 @@ public static class ApiModel { public final String brandingSecondary; public final java.net.URL brandingLogoUrl; public final String brandingMessage; + public final String seed; public ApiModel(String baseUrl, String version, @@ -130,7 +136,8 @@ public ApiModel(String baseUrl, String brandingBackground, String brandingSecondary, java.net.URL brandingLogoUrl, - String brandingMessage + String brandingMessage, + String seed ) { this.baseUrl = baseUrl; this.version = version; @@ -139,6 +146,7 @@ public ApiModel(String baseUrl, this.brandingSecondary = brandingSecondary; this.brandingLogoUrl = brandingLogoUrl; this.brandingMessage = brandingMessage; + this.seed = seed; } } } From 123fb6a09485d15d1b376723c1af9f59352acb7c Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 5 Jul 2021 12:13:31 +0200 Subject: [PATCH 060/310] add the method checkSeed() --- .../nivio/config/NivioConfigPropertiesTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java index 81c0c23e6..1734cc7d4 100644 --- a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java +++ b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java @@ -95,4 +95,17 @@ void checksBrandingMessage() { ConstraintViolation[] constraintViolations = (ConstraintViolation[]) validate.toArray(ConstraintViolation[]::new); assertThat(constraintViolations[0].getMessage()).isEqualTo("brandingMessage must be a valid string"); } + + @Test + void checkSeed() + { + NivioConfigProperties props = new NivioConfigProperties(); + props.setSeed("*!W13"); + Set> validate = localValidatorFactoryBean.getValidator().validate(props); + + assertThat(validate).isNotEmpty(); + ConstraintViolation[] constraintViolations = (ConstraintViolation[]) validate.toArray(ConstraintViolation[]::new); + assertThat(constraintViolations[0].getMessage()).isEqualTo("seed must be a valid landscape configuration"); + } + } \ No newline at end of file From 07cb1c1c3ba1abfa6f70c196cb616d75f9ac53b6 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 5 Jul 2021 12:30:30 +0200 Subject: [PATCH 061/310] delete the seed properties --- .../nivio/config/NivioConfigProperties.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java index dd0cbcd28..4006683f3 100644 --- a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java +++ b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java @@ -40,8 +40,7 @@ public class NivioConfigProperties { private String brandingMessage; //iconFolder: /a/local/path - private String seed; - + public String getBaseUrl() { return baseUrl; } @@ -106,9 +105,7 @@ public void setBrandingMessage(String brandingMessage) { this.brandingMessage = brandingMessage; } - public String getSeed(){ return seed; } - public void setSeed(String seed){ this.seed = seed;} public ApiModel getApiModel() { java.net.URL brandingLogoUrl = null; @@ -116,7 +113,7 @@ public ApiModel getApiModel() { brandingLogoUrl = this.brandingLogoUrl != null ? new java.net.URL(getBrandingLogoUrl()) : null; } catch (MalformedURLException ignored) { } - return new ApiModel(baseUrl, version, brandingForeground, brandingBackground, brandingSecondary, brandingLogoUrl, brandingMessage,seed); + return new ApiModel(baseUrl, version, brandingForeground, brandingBackground, brandingSecondary, brandingLogoUrl, brandingMessage); } @JsonInclude(JsonInclude.Include.NON_NULL) @@ -128,7 +125,7 @@ public static class ApiModel { public final String brandingSecondary; public final java.net.URL brandingLogoUrl; public final String brandingMessage; - public final String seed; + public ApiModel(String baseUrl, String version, @@ -136,8 +133,8 @@ public ApiModel(String baseUrl, String brandingBackground, String brandingSecondary, java.net.URL brandingLogoUrl, - String brandingMessage, - String seed + String brandingMessage + ) { this.baseUrl = baseUrl; this.version = version; @@ -146,7 +143,7 @@ public ApiModel(String baseUrl, this.brandingSecondary = brandingSecondary; this.brandingLogoUrl = brandingLogoUrl; this.brandingMessage = brandingMessage; - this.seed = seed; + } } } From bad58eb55b81155ebbaac9a941823c5c7fa2d1d1 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 5 Jul 2021 12:31:42 +0200 Subject: [PATCH 062/310] delete the method checkSeed() --- .../nivio/config/NivioConfigPropertiesTest.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java index 1734cc7d4..5e8b461e9 100644 --- a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java +++ b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java @@ -96,16 +96,6 @@ void checksBrandingMessage() { assertThat(constraintViolations[0].getMessage()).isEqualTo("brandingMessage must be a valid string"); } - @Test - void checkSeed() - { - NivioConfigProperties props = new NivioConfigProperties(); - props.setSeed("*!W13"); - Set> validate = localValidatorFactoryBean.getValidator().validate(props); - assertThat(validate).isNotEmpty(); - ConstraintViolation[] constraintViolations = (ConstraintViolation[]) validate.toArray(ConstraintViolation[]::new); - assertThat(constraintViolations[0].getMessage()).isEqualTo("seed must be a valid landscape configuration"); - } } \ No newline at end of file From dafcf586c0c9a05e99c9946618b18d837319fb7a Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 5 Jul 2021 10:29:07 +0200 Subject: [PATCH 063/310] [#563] showing configured kpis --- .../Landscape/Dashboard/StatusBarLayout.tsx | 76 +++++++++++++++++-- src/main/app/src/interfaces.ts | 2 +- .../de/bonndan/nivio/assessment/Status.java | 11 ++- .../bonndan/nivio/assessment/StatusValue.java | 4 +- .../nivio/assessment/kpi/AbstractKPI.java | 8 +- .../nivio/assessment/kpi/ConditionKPI.java | 26 +++++-- .../nivio/assessment/kpi/CustomKPI.java | 53 ++++++++++--- .../nivio/assessment/kpi/HealthKPI.java | 5 ++ .../de/bonndan/nivio/assessment/kpi/KPI.java | 34 ++++++++- .../nivio/assessment/kpi/RangeApiModel.java | 23 ++++++ .../nivio/assessment/kpi/ScalingKPI.java | 28 ++++++- .../de/bonndan/nivio/model/Landscape.java | 3 +- .../bonndan/nivio/model/LandscapeConfig.java | 4 +- .../nivio/assessment/AssessableTest.java | 40 +++++++--- .../bonndan/nivio/assessment/StatusTest.java | 17 +++++ .../nivio/assessment/StatusValueTest.java | 6 +- .../nivio/assessment/kpi/CustomKPITest.java | 14 ++++ .../bonndan/nivio/assessment/kpi/KPITest.java | 58 ++++++++++++++ 18 files changed, 358 insertions(+), 54 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java create mode 100644 src/test/java/de/bonndan/nivio/assessment/StatusTest.java create mode 100644 src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java diff --git a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx index 0b6b89162..e99d2975f 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx @@ -2,13 +2,27 @@ import React, { useContext, useState } from 'react'; import { IGroup } from '../../../interfaces'; import StatusChip from '../../StatusChip/StatusChip'; import Button from '@material-ui/core/Button'; -import { Card, CardHeader, Table, TableBody, TableCell, TableRow } from '@material-ui/core'; +import { + AppBar, + Box, + Card, + CardHeader, + Tab, + Table, + TableBody, + TableCell, + TableRow, + Tabs, +} from '@material-ui/core'; import { LandscapeContext } from '../../../Context/LandscapeContext'; import componentStyles from '../../../Resources/styling/ComponentStyles'; import IconButton from '@material-ui/core/IconButton'; -import { Close } from '@material-ui/icons'; +import { Close, Settings, Warning } from '@material-ui/icons'; import ItemAvatar from '../Modals/Item/ItemAvatar'; import GroupAvatar from '../Modals/Group/GroupAvatar'; +import { a11yProps, TabPanel } from '../Utils/TabUtils'; +import CardContent from '@material-ui/core/CardContent'; +import Typography from '@material-ui/core/Typography'; interface Props { onItemClick: Function; @@ -22,6 +36,7 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { const context = useContext(LandscapeContext); const componentClasses = componentStyles(); const [visible, setVisible] = useState(true); + const [currentTab, setCurrentTab] = React.useState(0); const getItems = (group: IGroup) => { return group.items.map((item) => { @@ -103,7 +118,27 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { }); }; + const changeTab = (event: React.ChangeEvent<{}>, newValue: number) => { + setCurrentTab(newValue); + }; + if (!visible) return null; + + const kpiConfig = context.landscape?.kpis; + let kpis : JSX.Element[] = []; + if (kpiConfig) { + for (let key of Object.keys(kpiConfig)) + { + const kpi = kpiConfig[key]; + kpis.push( + + {key} +

{kpi.description}

+ + ) + } + } + return ( = ({ onItemClick, onGroupClick }) => {
} /> - - - {context.landscape ? getGroups(context.landscape.groups) : null} - {context.landscape?.groups.map((group) => getItems(group))} - -
+ + + } + label={'warnings'} + style={{ minWidth: 50 }} + title={'Warnings'} + {...a11yProps(0, 'statusbar')} + /> + } + label={'kpis'} + style={{ minWidth: 50 }} + title={'KPIs'} + {...a11yProps(1, 'statusbar')} + /> + + + + + + + {context.landscape ? getGroups(context.landscape.groups) : null} + {context.landscape?.groups.map((group) => getItems(group))} + +
+
+ + {kpis} + +
); }; diff --git a/src/main/app/src/interfaces.ts b/src/main/app/src/interfaces.ts index da85809aa..39fa82be7 100644 --- a/src/main/app/src/interfaces.ts +++ b/src/main/app/src/interfaces.ts @@ -18,6 +18,7 @@ export interface ILandscape { links?: ILinks; lastUpdate?: string; groups: IGroup[]; + kpis?: IKpis; } export interface IProcessLog { @@ -38,7 +39,6 @@ export interface IConfig { groupBlacklist?: Array; labelBlacklist?: Array; branding?: IBranding; - kpis?: IKpis; } export interface IKpis { diff --git a/src/main/java/de/bonndan/nivio/assessment/Status.java b/src/main/java/de/bonndan/nivio/assessment/Status.java index ddefb5f6e..9ed846105 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Status.java +++ b/src/main/java/de/bonndan/nivio/assessment/Status.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonValue; import org.springframework.util.StringUtils; +import java.util.Objects; + public enum Status { UNKNOWN("grey", 0), @@ -52,8 +54,11 @@ public String toString() { return status; } - public boolean isHigherThan(Status current) { - return order > current.order; + public static class Comparator implements java.util.Comparator { + public int compare(Status s1, Status s2) { + if (Objects.requireNonNull(s1).order > Objects.requireNonNull(s2).order) return 1; + if (s1.equals(s2)) return 0; + return -1; + } } - } diff --git a/src/main/java/de/bonndan/nivio/assessment/StatusValue.java b/src/main/java/de/bonndan/nivio/assessment/StatusValue.java index df7d1d303..1d080f19a 100644 --- a/src/main/java/de/bonndan/nivio/assessment/StatusValue.java +++ b/src/main/java/de/bonndan/nivio/assessment/StatusValue.java @@ -152,9 +152,7 @@ public String getMaxField() { public static class Comparator implements java.util.Comparator { public int compare(StatusValue s1, StatusValue s2) { - if (Objects.requireNonNull(s1.status).isHigherThan(Objects.requireNonNull(s2.status))) return 1; - if (s1.status.equals(s2.status)) return 0; - return -1; + return Objects.requireNonNull(s1.status).compareTo(Objects.requireNonNull(s2.status)); } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java index 34e0efb4c..c6aa186df 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java @@ -15,7 +15,7 @@ public abstract class AbstractKPI implements KPI { protected String messageTemplate = "%s"; - private String description; + protected String description; private boolean enabled = true; protected Function valueFunction; @@ -23,14 +23,14 @@ public abstract class AbstractKPI implements KPI { @NonNull protected Function msgFunction = component -> String.format(messageTemplate, valueFunction.apply(component)); - public AbstractKPI() { + protected AbstractKPI() { } /** * @param valueFunction a function returning the value to assess * @param msgFunction a function returning the status message */ - public AbstractKPI(@NonNull Function valueFunction, + protected AbstractKPI(@NonNull Function valueFunction, @Nullable Function msgFunction ) { this.valueFunction = Objects.requireNonNull(valueFunction); @@ -49,7 +49,7 @@ public AbstractKPI(@NonNull Function valueFunction, public List getStatusValues(Component component) { if (valueFunction == null) { - throw new RuntimeException("Value function not initialized "); + throw new IllegalStateException("Value function not initialized "); } String value = valueFunction.apply(component); String message = msgFunction.apply(component); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java index bf8904776..990d189c9 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java @@ -6,25 +6,31 @@ import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Evaluates the "condition.*" labels, see {@link InputFormatHandlerKubernetes} * - * this is similiar to the {@link HealthKPI}, it only works on a different field. + * this is similar to the {@link HealthKPI}, it only works on a different field. */ public class ConditionKPI implements KPI { public static final String IDENTIFIER = "condition"; + private static final Map> matches = new LinkedHashMap<>(); + + static { + matches.put(Status.RED, List.of("One condition is not met.")); + matches.put(Status.GREEN, List.of("All conditions are met.")); + } + private boolean enabled = true; @Override + @NonNull public List getStatusValues(Component component) { if (!(component instanceof Labeled)) return new ArrayList<>(); @@ -63,6 +69,16 @@ public boolean isEnabled() { return enabled; } + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return matches; + } + public void setEnabled(boolean enabled) { this.enabled = enabled; } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java index 6cabba353..163ae97bf 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java @@ -7,6 +7,8 @@ import de.bonndan.nivio.model.Labeled; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.lang.Nullable; import java.util.*; @@ -20,6 +22,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class CustomKPI extends AbstractKPI { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomKPI.class); + public static final String SEPARATOR = ";"; /** @@ -30,14 +34,17 @@ public class CustomKPI extends AbstractKPI { /** * For each {@link Status} a set of regular expressions can be defined which indicate the status. */ - private final Map>> matches = new HashMap<>(); + private final Map>> matchSpecs = new HashMap<>(); protected String label; + protected Map> matchers; + /** * */ public CustomKPI() { + //required for deserialization } @Override @@ -47,10 +54,14 @@ public void init(KPIConfig kpiConfig) { if (kpiConfig.label != null) { label = kpiConfig.label; } + if (kpiConfig.description != null) { + description = kpiConfig.description; + } this.setEnabled(kpiConfig.enabled); if (!StringUtils.isEmpty(kpiConfig.messageTemplate)) { messageTemplate = kpiConfig.messageTemplate; } + ranges = asRanges(kpiConfig.label, kpiConfig.ranges); addSpecsFromConfig(kpiConfig.matches); } @@ -59,9 +70,9 @@ public void init(KPIConfig kpiConfig) { if (component instanceof Labeled) { return ((Labeled) component).getLabel(label); } - throw new RuntimeException("Custom KPIs can only evaluate labels (custom fields)."); + LOGGER.error("Custom KPIs can only evaluate labels (custom fields)."); + return null; }; - } @Override @@ -75,12 +86,12 @@ protected List getStatusValues(@Nullable String value, @Nullable St break; } - if (!matches.containsKey(status)) { + if (!matchSpecs.containsKey(status)) { continue; } - boolean anyMatch = false; + var anyMatch = false; if (value != null) { - anyMatch = matches.get(status).stream().anyMatch(stringBooleanFunction -> stringBooleanFunction.apply(value)); + anyMatch = matchSpecs.get(status).stream().anyMatch(stringBooleanFunction -> stringBooleanFunction.apply(value)); } if (anyMatch) { values.add(new StatusValue(label, status, message)); @@ -91,6 +102,19 @@ protected List getStatusValues(@Nullable String value, @Nullable St return values; } + @Override + public Map getRanges() { + if (ranges == null) return null; + return sorted( + ranges.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> new RangeApiModel(entry.getValue()))) + ); + } + + @Override + public Map> getMatches() { + return sorted(matchers); + } + protected Map> asRanges(String label, Map ranges) { Map> rangeMap = new HashMap<>(); if (ranges == null) { @@ -136,8 +160,8 @@ protected void addSpecsFromConfig(@Nullable Map input) { Map statusPatterns = new HashMap<>(); if (input != null) { input.forEach((s, s2) -> statusPatterns.put(Status.from(s), s2)); - addSpecs(statusPatterns); } + addSpecs(statusPatterns); } protected void addSpecs(@Nullable Map statusPatterns) { @@ -145,17 +169,24 @@ protected void addSpecs(@Nullable Map statusPatterns) { return; } - statusPatterns.forEach((status, strings) -> { - List> specs = Arrays.stream(strings.split(SEPARATOR)).map(s -> { + Map> matchersPerStatus = statusPatterns.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + e -> Arrays.asList(e.getValue().split(SEPARATOR)) + )); + + matchersPerStatus.forEach((status, strings) -> { + List> specs = strings.stream().map(s -> { try { - Pattern p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); + var p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); return (Function) s1 -> p.matcher(s1).matches(); } catch (Exception e) { throw new ProcessingException(String.format("Failed to initialize KPI %s matcher pattern ", this.label), e); } }).collect(Collectors.toList()); - matches.put(status, specs); + matchSpecs.put(status, specs); }); + + this.matchers = matchersPerStatus; } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java index b013f0e81..bd10ef4b4 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java @@ -20,6 +20,11 @@ public class HealthKPI extends CustomKPI { Status.RED, UNHEALTHY ); + @Override + public String getDescription() { + return "Evaluates the 'health' label values healthy and unhealthy."; + } + public HealthKPI() { super(); label = Label.health.name(); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java index 9fee4a023..2225ee5dc 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java @@ -1,5 +1,7 @@ package de.bonndan.nivio.assessment.kpi; +import com.fasterxml.jackson.annotation.JsonInclude; +import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Component; @@ -7,21 +9,25 @@ import org.springframework.lang.Nullable; import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * Key Performance Indicator * * Used to evaluate {@link Component}s. */ +@JsonInclude(JsonInclude.Include.NON_NULL) public interface KPI { /** * Controlled initialisation. * - * @throws ProcessingException if initialisation fails (eg regex compiling) * @param kpiConfig optional config + * @throws ProcessingException if initialisation fails (eg regex compiling) */ - default void init(@Nullable KPIConfig kpiConfig) {} + default void init(@Nullable KPIConfig kpiConfig) { + } /** * Returns the status evaluation of the component on the configured field. @@ -43,4 +49,28 @@ default void init(@Nullable KPIConfig kpiConfig) {} * @return true if active */ boolean isEnabled(); + + /** + * Returns the calculated range for the statuses for the API. + * + * @return ranges if present, sorted from best to worst, otherwise null + */ + @Nullable + Map getRanges(); + + /** + * Returns the calculated matches for the statuses for the API. + * + * @return ranges if present, sorted from best to worst, otherwise null + */ + @Nullable + Map> getMatches(); + + @Nullable + default Map sorted(@Nullable final Map inner) { + if (inner == null) return null; + var sorted = new TreeMap(new Status.Comparator()); + inner.forEach(sorted::put); + return sorted; + } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java b/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java new file mode 100644 index 000000000..38f522108 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java @@ -0,0 +1,23 @@ +package de.bonndan.nivio.assessment.kpi; + +import org.apache.commons.lang3.Range; +import org.springframework.lang.NonNull; + +import java.util.Objects; + +public class RangeApiModel { + + private final Range range; + + public RangeApiModel(@NonNull final Range range) { + this.range = Objects.requireNonNull(range, "Non null range is required"); + } + + public String getMinimum() { + return range.getMinimum().toString(); + } + + public String getMaximum() { + return range.getMaximum().toString(); + } +} diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java index 4356b2a8e..61fcc737e 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java @@ -6,12 +6,15 @@ import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.RelationType; +import org.apache.commons.lang3.Range; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import java.util.Collections; import java.util.List; +import java.util.Map; /** * This KPI evaluates the scale label and tries to find bottlenecks where providers for many items are down or not scaled. @@ -30,6 +33,18 @@ public class ScalingKPI extends AbstractKPI { private static final Logger LOGGER = LoggerFactory.getLogger(ScalingKPI.class); public static final String SCALED_TO_ZERO = "scaled to zero"; + private final Map ranges = Map.of( + Status.GREEN, new RangeApiModel(Range.between(1D, Double.POSITIVE_INFINITY)), + Status.YELLOW, new RangeApiModel(Range.between(0D, 0D)), + Status.ORANGE, new RangeApiModel(Range.between(0D, 0D)), + Status.RED, new RangeApiModel(Range.between(0D, 0D)) + ); + + @Override + public String getDescription() { + return "Turns yellow if the 'scale' label is zero. Turns orange or red if is also is a data sink or provider."; + } + @NonNull @Override public List getStatusValues(Component component) { @@ -60,7 +75,7 @@ private List getItemStatusValues(Item component) { Status status = Status.YELLOW; String message = SCALED_TO_ZERO; if (usedAsProvider > 0) { - status = Status.RED; + status = Status.RED; message += " and provider for " + usedAsProvider + " items"; } else if (usedAsDataTarget > 0) { status = Status.ORANGE; @@ -90,4 +105,15 @@ protected List getStatusValues(String value, String message) { return Collections.emptyList(); } + @Override + @Nullable + public Map getRanges() { + return sorted(ranges); + } + + @Override + @Nullable + public Map> getMatches() { + return null; + } } diff --git a/src/main/java/de/bonndan/nivio/model/Landscape.java b/src/main/java/de/bonndan/nivio/model/Landscape.java index 7e05b67aa..969ca71de 100644 --- a/src/main/java/de/bonndan/nivio/model/Landscape.java +++ b/src/main/java/de/bonndan/nivio/model/Landscape.java @@ -288,8 +288,7 @@ public String getIcon() { * * @return kpis, configured and initialized */ - @JsonIgnore - public Map getKpis() { + public Map getKpis() { return kpis; } diff --git a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java index 26b4560ff..fda6e439a 100644 --- a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java +++ b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.assessment.kpi.KPIConfig; import io.swagger.v3.oas.annotations.media.Schema; @@ -135,10 +136,11 @@ public void setMaxDistanceLimitFactor(Float maxDistanceLimitFactor) { } /** - * The active KPIs. + * The configured KPIs. * * @return all active {@link AbstractKPI}s with their unique identifier */ + @JsonIgnore public Map getKPIs() { return kpis; } diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java index 57b28fc8b..917bc56e0 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java @@ -2,14 +2,14 @@ import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.assessment.kpi.RangeApiModel; +import de.bonndan.nivio.model.*; +import org.apache.commons.lang3.Range; import org.junit.jupiter.api.Test; import org.springframework.lang.NonNull; import java.util.*; +import java.util.function.Function; import static de.bonndan.nivio.assessment.StatusValue.SUMMARY_LABEL; import static de.bonndan.nivio.model.ItemFactory.getTestItem; @@ -51,13 +51,13 @@ void skipsDisabledKPIs() { var parent = new TestAssessable(List.of(child1, child2)); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { return new ArrayList<>(); } }); - var disabled = new AbstractKPI(component -> null, null) { + var disabled = new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { throw new RuntimeException("This should never happen."); @@ -76,7 +76,7 @@ public void withItem() { item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { return new ArrayList<>(); @@ -109,7 +109,7 @@ public void uniqueStatusLists() { item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { return List.of( @@ -147,7 +147,7 @@ public void groupSummary() { foo.addItem(item2); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { return new ArrayList<>(); @@ -183,7 +183,7 @@ public void isSorted() { item.setLabel(Label.withPrefix(Label.status, "baz", StatusValue.LABEL_SUFFIX_MESSAGE), "not so bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override protected List getStatusValues(String value, String message) { return new ArrayList<>(); @@ -209,7 +209,7 @@ protected List getStatusValues(String value, String message) { class TestAssessable implements Assessable { - private Set statusValues = new HashSet<>(); + private final Set statusValues = new HashSet<>(); private final List children; TestAssessable(List children) { @@ -226,11 +226,13 @@ void setStatusValue(@NonNull StatusValue statusValue) { } @Override + @NonNull public String getIdentifier() { return "test"; } @Override + @NonNull public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { return FullyQualifiedIdentifier.build("test", null, null); } @@ -275,4 +277,20 @@ public List getChildren() { return children; } } + + private abstract static class TestKPI extends AbstractKPI { + public TestKPI(Function valueFunction, Function msgFunction) { + super(valueFunction, msgFunction); + } + + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return null; + } + } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/StatusTest.java b/src/test/java/de/bonndan/nivio/assessment/StatusTest.java new file mode 100644 index 000000000..2762d8c96 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/StatusTest.java @@ -0,0 +1,17 @@ +package de.bonndan.nivio.assessment; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class StatusTest { + + @Test + void comparator() { + Status green = Status.GREEN; + Status red = Status.RED; + assertEquals(-1, new Status.Comparator().compare(green, red)); + assertEquals(0, new Status.Comparator().compare(green, green)); + assertEquals(1, new Status.Comparator().compare(red, green)); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java b/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java index 8dc626ab7..9848607f0 100644 --- a/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java @@ -20,9 +20,11 @@ void mustHaveField() { void comparator() { StatusValue green = new StatusValue("foo", Status.GREEN); StatusValue red = new StatusValue("foo", Status.RED); - assertEquals(-1, new StatusValue.Comparator().compare(green, red)); + StatusValue yellow = new StatusValue("foo", Status.YELLOW); + assertEquals(-3, new StatusValue.Comparator().compare(green, red)); assertEquals(0, new StatusValue.Comparator().compare(green, green)); - assertEquals(1, new StatusValue.Comparator().compare(red, green)); + assertEquals(1, new StatusValue.Comparator().compare(yellow, green)); + assertEquals(3, new StatusValue.Comparator().compare(red, green)); } @Test diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java index cffec6ec5..bb8b3c218 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java @@ -16,6 +16,7 @@ import java.util.Map; import static de.bonndan.nivio.model.ItemFactory.getTestItem; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class CustomKPITest { @@ -48,6 +49,19 @@ void testWithRanges1(String value, String status) { Assertions.assertEquals(status, statusValue.getStatus().getName().toLowerCase(Locale.ROOT)); } + @Test + void testUsesConfigValues() { + CustomKPI test = new CustomKPI(); + kpiConfig.ranges = getRangeMap(); + kpiConfig.description = "bar"; + + //when + test.init(kpiConfig); + + //then + assertThat(test.getDescription()).isEqualTo("bar"); + } + @Test void testoutOfRange() { CustomKPI test = new CustomKPI(); diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java new file mode 100644 index 000000000..08e70f54f --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java @@ -0,0 +1,58 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.model.Component; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class KPITest { + + @Test + void sorted() { + + KPI test = new KPI() { + @Override + public List getStatusValues(Component component) { + return null; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return sorted( + Map.of(Status.RED, List.of("foo"), Status.BROWN, List.of("bar", "baz"), Status.GREEN, List.of("hihi")) + ); + } + }; + + //when + Map> matches = test.getMatches(); + + //then + Iterator iterator = matches.keySet().iterator(); + assertThat(iterator.next()).isEqualTo(Status.GREEN); + assertThat(iterator.next()).isEqualTo(Status.RED); + assertThat(iterator.next()).isEqualTo(Status.BROWN); + } +} \ No newline at end of file From b1b9bfcf33ec3a847942fae79d4c3a229ebbc4b0 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 07:33:38 +0200 Subject: [PATCH 064/310] better debugging for a rare error when linked hashmap cannot be cast to item description --- .../nivio/input/SourceReferencesResolver.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java index 4b6d9f430..8ea784f0e 100644 --- a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java +++ b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java @@ -3,6 +3,8 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.LandscapeSource; import de.bonndan.nivio.util.URLHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; @@ -15,6 +17,8 @@ */ public class SourceReferencesResolver { + private static final Logger LOGGER = LoggerFactory.getLogger(SourceReferencesResolver.class); + private final InputFormatHandlerFactory formatFactory; private final ProcessLog log; private final ApplicationEventPublisher eventPublisher; @@ -30,7 +34,7 @@ public SourceReferencesResolver(@NonNull final InputFormatHandlerFactory formatF public void resolve(final LandscapeDescription landscapeDescription) { - final URL baseUrl = getBaseUrl(landscapeDescription.getSource()); + final var baseUrl = getBaseUrl(landscapeDescription.getSource()); landscapeDescription.getSourceReferences().forEach(ref -> { InputFormatHandler formatHandler; @@ -59,14 +63,15 @@ public void resolve(final LandscapeDescription landscapeDescription) { eventPublisher.publishEvent(new ProcessingErrorEvent(landscapeDescription.getFullyQualifiedIdentifier(), ex)); landscapeDescription.setIsPartial(true); } catch (RuntimeException ex) { - log.warn(ex.getMessage()); + LOGGER.warn("Could not resolve source reference {}: {}", ref, ex.getMessage(), ex); + log.warn(String.format("Failed to resolve source reference %s properly.", ref.getUrl())); landscapeDescription.setIsPartial(true); } }); } private URL getBaseUrl(LandscapeSource source) { - if(source != null) { + if (source != null) { return source.getURL().flatMap(URLHelper::getParentPath).orElse(null); } return null; @@ -76,7 +81,7 @@ private URL getBaseUrl(LandscapeSource source) { private String getCauseMessage(Throwable cause) { String s = cause.getMessage().split("\\[")[0]; if (s.endsWith("at ")) { - s = s.substring(0, s.length()-3); + s = s.substring(0, s.length() - 3); } return s.trim(); From 20e003b16d0567a5930962f0e0c3c28b7f10377c Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 07:36:24 +0200 Subject: [PATCH 065/310] cleanup --- src/main/java/de/bonndan/nivio/model/ItemFactory.java | 9 ++++++--- .../java/de/bonndan/nivio/model/LandscapeFactory.java | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/model/ItemFactory.java b/src/main/java/de/bonndan/nivio/model/ItemFactory.java index 9df2c1279..e5a3df465 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemFactory.java +++ b/src/main/java/de/bonndan/nivio/model/ItemFactory.java @@ -14,10 +14,13 @@ public class ItemFactory { + private ItemFactory() { + } + private static final Logger logger = LoggerFactory.getLogger(ItemFactory.class); public static Item getTestItem(String group, String identifier) { - Landscape landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); + var landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); return getTestItem(group, identifier, landscape); } @@ -27,7 +30,7 @@ public static Item getTestItem(String group, String identifier, Landscape landsc } public static ItemBuilder getTestItemBuilder(String group, String identifier) { - Landscape landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); + var landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); return ItemBuilder.anItem().withGroup(group).withIdentifier(identifier).withLandscape(landscape); } @@ -70,7 +73,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescription description) { Objects.requireNonNull(item, "Item is null"); if (description == null) { - logger.warn(String.format("ItemDescription for item %s is null in assignAllValues", item.getIdentifier())); + logger.warn("ItemDescription for item {} is null in assignAllValues", item.getIdentifier()); return item; } diff --git a/src/main/java/de/bonndan/nivio/model/LandscapeFactory.java b/src/main/java/de/bonndan/nivio/model/LandscapeFactory.java index 18c198524..e260f158f 100644 --- a/src/main/java/de/bonndan/nivio/model/LandscapeFactory.java +++ b/src/main/java/de/bonndan/nivio/model/LandscapeFactory.java @@ -14,6 +14,8 @@ public class LandscapeFactory { private static final KPIFactory kpiFactory = new KPIFactory(); + private LandscapeFactory() {} + /** * Creates a new landscape impl. * @@ -21,7 +23,7 @@ public class LandscapeFactory { */ public static Landscape createFromInput(@NonNull final LandscapeDescription input) { - Landscape landscape = new Landscape( + var landscape = new Landscape( input.getIdentifier(), getGroups(input.getIdentifier()), input.getName(), @@ -30,7 +32,7 @@ public static Landscape createFromInput(@NonNull final LandscapeDescription inpu input.getDescription(), input.getSource(), input.getConfig(), - new ProcessLog(LoggerFactory.getLogger(Landscape.class), input.getIdentifier()), + new ProcessLog(LoggerFactory.getLogger(LandscapeFactory.class), input.getIdentifier()), kpiFactory.getConfiguredKPIs(input.getConfig().getKPIs()) ); input.getLabels().forEach((s, s2) -> landscape.getLabels().put(s, s2)); From d31b9ca995f0482824ec12d6bc708dec48507b16 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 08:48:30 +0200 Subject: [PATCH 066/310] [#563] added lifecycle matchers for explanation --- .../java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java | 2 +- .../java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java index 990d189c9..f62a44d8d 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java @@ -76,7 +76,7 @@ public Map getRanges() { @Override public Map> getMatches() { - return matches; + return sorted(matches); } public void setEnabled(boolean enabled) { diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java index a61b3a2e5..0e8ca97f7 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java @@ -21,12 +21,17 @@ public LifecycleKPI() { .map(lifecycle -> "Phase: " + lifecycle.name().toLowerCase(Locale.ROOT).replace("_", " ")) .orElse("unknown"); + matchers = Map.of( + Status.GREEN, List.of(Lifecycle.PRODUCTION.name()), + Status.ORANGE, List.of(Lifecycle.END_OF_LIFE.name()) + ); + setDescription("This KPI evaluates the lifecycle label for known values (PLANNED, PRODUCTION)."); } @Override protected List getStatusValues(String value, String message) { - Lifecycle lifecycle = Lifecycle.from(value); + var lifecycle = Lifecycle.from(value); if (Lifecycle.PRODUCTION.equals(lifecycle)) { return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.GREEN, message)); } From 0e7283b5eb1319544b534957af1344909de1a224 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 08:48:49 +0200 Subject: [PATCH 067/310] [#563] missing pet clinic radiation level --- src/test/resources/example/pet_clinic.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/resources/example/pet_clinic.yml b/src/test/resources/example/pet_clinic.yml index dfb282b11..85c53b1f7 100644 --- a/src/test/resources/example/pet_clinic.yml +++ b/src/test/resources/example/pet_clinic.yml @@ -13,7 +13,8 @@ config: ranges: GREEN: 0;99.999999 YELLOW: 100;199.999999 - RED: 200;499.999999 + ORANGE: 200;399.999999 + RED: 400;499.999999 BROWN: 500;1000000 From 5715d090eccf8b3e55394819706f41d390c89b22 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 08:49:47 +0200 Subject: [PATCH 068/310] [#563] cleanup --- src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java index a8f1e71f0..14734d046 100644 --- a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java +++ b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java @@ -45,7 +45,7 @@ private Optional getDemoLandscapeDescription() { String demoFile = absPath + "/src/test/resources/example/pet_clinic.yml"; File file = new File(demoFile); if (!file.exists()) { - LOGGER.error(String.format("Failed to read pet clinic demo data from %s", demoFile)); + LOGGER.error("Failed to read pet clinic demo data from {}", demoFile); return Optional.empty(); } From 273f3aa4c4c5e692c8993dab5888db2cf05c8ec6 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:29:10 +0200 Subject: [PATCH 069/310] removed the unused import org.springframework.validation.annotation.Validated --- src/main/java/de/bonndan/nivio/config/SeedProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index d124f9414..52f9ac65c 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.config; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; + @ConfigurationProperties(prefix = "nivio") From d28b5f817003687c0b9cb5f3b97fbf622a65ce43 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:30:21 +0200 Subject: [PATCH 070/310] removed the unused import org.springframework.validation.annotation.Validated --- .../bonndan/nivio/input/external/github/GitHubProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java index 0c72542ed..54858449d 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.input.external.github; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; + @ConfigurationProperties(prefix = "github") From 1972fc76420ab590ab15ab88a042b94a5474ef2f Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:31:53 +0200 Subject: [PATCH 071/310] remove the unused import and the duplicate import --- .../de/bonndan/nivio/input/external/sonar/SonarProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java index 469c79a74..c1902397c 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.input.external.sonar; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; + @ConfigurationProperties(prefix = "sonar") From 22dfe92cc300b91f722d57e9ece2ec3761f7207f Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:34:05 +0200 Subject: [PATCH 072/310] remove the unused import de.bonndan.nivio.config.ConfigurableEnvVars --- .../de/bonndan/nivio/input/external/sonar/SonarConfig.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java index a8b2c2c94..4d1bd645f 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java @@ -7,9 +7,6 @@ import java.util.Optional; -import static de.bonndan.nivio.config.ConfigurableEnvVars.*; -import java.util.Optional; - @Configuration @EnableConfigurationProperties(SonarProperties.class) public class SonarConfig { From d13f63110afe8b7d4b4df91dc1cfc4e98c2986cd Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:35:49 +0200 Subject: [PATCH 073/310] remove the unused LOGGER private field --- .../de/bonndan/nivio/input/external/LinkHandlerFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java index 7edd17fb8..0f64a5fb4 100644 --- a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java +++ b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java @@ -22,7 +22,7 @@ @Component public class LinkHandlerFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(LinkHandlerFactory.class); + // private static final Logger LOGGER = LoggerFactory.getLogger(LinkHandlerFactory.class); public static final String GITHUB = "github"; private static final String SONAR = "sonar"; From 6d510e56a2b080362241d10f4086ec6baac8b3f8 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:38:11 +0200 Subject: [PATCH 074/310] modify some assertions in the method dependentAssertions() --- .../bonndan/nivio/input/external/github/GitHubConfigTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java index cfa1b8c1b..bbe1dd299 100644 --- a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java @@ -42,7 +42,7 @@ void dependentAssertions(){ // executed only if the previous assertion is valid assertAll("password", ()-> assertTrue(password.contains("45")), - ()-> assertTrue(password.length()==9)); + ()-> assertEquals(9,password.length())); }, ()->{String oauth = gitHubProperties.getOauth(); @@ -56,7 +56,7 @@ void dependentAssertions(){ assertNotNull(jwt); // executed only if the previous assertion is valid assertAll("jwt", - ()->assertTrue(jwt.length()==12), + ()->assertEquals(12,jwt.length()), ()->assertTrue(jwt.endsWith("ken")) ); From 9daa9ef273e2aca38a5011ca2cc998ca2a8bd9c4 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Tue, 6 Jul 2021 11:50:25 +0200 Subject: [PATCH 075/310] remove some unused import and blocks of commented-out lines of code --- .../bonndan/nivio/input/external/LinkHandlerFactory.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java index 0f64a5fb4..dbc0aa48e 100644 --- a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java +++ b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java @@ -6,13 +6,10 @@ import de.bonndan.nivio.input.external.openapi.OpenAPILinkHandler; import de.bonndan.nivio.input.external.sonar.SonarLinkHandler; import de.bonndan.nivio.input.external.springboot.SpringBootHealthHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; - import java.util.Map; import java.util.Optional; @@ -22,8 +19,6 @@ @Component public class LinkHandlerFactory { - // private static final Logger LOGGER = LoggerFactory.getLogger(LinkHandlerFactory.class); - public static final String GITHUB = "github"; private static final String SONAR = "sonar"; private static final String SPRING_HEALTH = "spring.health"; @@ -57,10 +52,6 @@ private Optional createHandler(String key, Class Date: Tue, 6 Jul 2021 13:10:22 +0200 Subject: [PATCH 076/310] Refactor Code --- docs/source/schema/Models/KPIConfig.rst | 2 +- .../schema/Models/LandscapeDescription.rst | 10 +- docs/source/schema/spec.json | 142 ++++---- .../nivio/assessment/AssessmentFactory.java | 6 +- .../nivio/assessment/kpi/KPIFactory.java | 1 + .../nivio/assessment/kpi/KubernetesKPI.java | 49 +++ .../input/kubernetes/DeploymentItem.java | 37 +- .../InputFormatHandlerKubernetes.java | 318 +++--------------- .../bonndan/nivio/input/kubernetes/Item.java | 61 ++-- .../kubernetes/PersistentVolumeClaimItem.java | 28 ++ .../kubernetes/PersistentVolumeItem.java | 28 ++ .../nivio/input/kubernetes/PodItem.java | 39 ++- .../input/kubernetes/ReplicaSetItem.java | 46 ++- .../nivio/input/kubernetes/ServiceItem.java | 19 +- .../input/kubernetes/StatefulSetItem.java | 19 +- .../nivio/assessment/kpi/KPIFactoryTest.java | 10 +- .../input/ComponentDescriptionValuesTest.java | 1 - .../input/kubernetes/DeploymentItemTest.java | 18 + .../{ => kubernetes}/KubernetesTest.java | 6 +- .../PersistentVolumeClaimItemTest.java | 78 +++++ .../nivio/model/LandscapeFactoryTest.java | 7 +- 21 files changed, 488 insertions(+), 437 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java rename src/test/java/de/bonndan/nivio/input/{ => kubernetes}/KubernetesTest.java (94%) create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index 8838e6fc9..e170f09ad 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -21,7 +21,7 @@ The configuration of landscape specific key performance indicators that derive s * - label - String - Key of the label to evaluate - - optional, defaults to null + - **required**, defaults to null - costs * - messageTemplate - String diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index dd41a02f8..c887e1a45 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -73,16 +73,16 @@ LandscapeDescription - - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - items - List - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 60951921a..a9900d882 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -191,39 +191,52 @@ "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", "example" : "4400FF" }, - "address" : { - "type" : "string", - "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." - }, - "type" : { - "type" : "string", - "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - "example" : "service|database|volume" - }, - "status" : { - "type" : "array", - "description" : "A list of statuses that works like hardcoded KPIs.", - "writeOnly" : true, - "items" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A list of statuses that works like hardcoded KPIs." + "address": { + "type": "string", + "description": "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." + }, + "type": { + "type": "string", + "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", + "example": "service|database|volume" + }, + "lifecycle": { + "type": "string", + "description": "The lifecycle state of an item.", + "writeOnly": true, + "enum": [ + "PLANNED", + "INTEGRATION", + "TEST", + "PRODUCTION", + "END_OF_LIFE", + "EOL" + ] + }, + "statuses": { + "type": "array", + "description": "A list of statuses that works like hardcoded KPIs.", + "writeOnly": true, + "items": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A list of statuses that works like hardcoded KPIs." }, - "description" : "A list of statuses that works like hardcoded KPIs." + "description": "A list of statuses that works like hardcoded KPIs." } }, - "statuses" : { - "type" : "array", - "description" : "A list of statuses that works like hardcoded KPIs.", - "writeOnly" : true, - "items" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A list of statuses that works like hardcoded KPIs." + "status": { + "type": "array", + "description": "A list of statuses that works like hardcoded KPIs.", + "writeOnly": true, + "items": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A list of statuses that works like hardcoded KPIs." }, - "description" : "A list of statuses that works like hardcoded KPIs." + "description": "A list of statuses that works like hardcoded KPIs." } }, "frameworks" : { @@ -237,12 +250,6 @@ "writeOnly" : true, "example" : "java: 8" }, - "lifecycle" : { - "type" : "string", - "description" : "The lifecycle state of an item.", - "writeOnly" : true, - "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] - }, "tags" : { "type" : "array", "items" : { @@ -261,16 +268,19 @@ "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." }, "KPIConfig" : { - "type" : "object", - "properties" : { - "description" : { - "type" : "string", - "description" : "Description of the purpose of the KPI" - }, - "label" : { - "type" : "string", - "description" : "Key of the label to evaluate", - "example" : "costs" + "required": [ + "label" + ], + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Description of the purpose of the KPI" + }, + "label": { + "type": "string", + "description": "Key of the label to evaluate", + "example": "costs" }, "messageTemplate" : { "type" : "string", @@ -397,33 +407,33 @@ "additionalProperties" : { "$ref" : "#/components/schemas/GroupDescription" }, - "description" : "Description of item groups (optional, can also be given in sources)." + "description": "Description of item groups (optional, can also be given in sources)." }, - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Additional labels for the landscape." + "labels": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Additional labels for the landscape." }, - "description" : "Additional labels for the landscape." + "description": "Additional labels for the landscape." }, - "items" : { - "type" : "array", - "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/ItemDescription" - } + "color": { + "type": "string" }, - "partial" : { - "type" : "boolean", - "description" : "marks that the landscape is not complete, but an update" + "icon": { + "type": "string" }, - "icon" : { - "type" : "string" + "items": { + "type": "array", + "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", + "writeOnly": true, + "items": { + "$ref": "#/components/schemas/ItemDescription" + } }, - "color" : { - "type" : "string" + "partial": { + "type": "boolean", + "description" : "marks that the landscape is not complete, but an update" }, "links" : { "type" : "object", diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java index e25752ee7..463c5bbdc 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java @@ -17,7 +17,7 @@ private AssessmentFactory() { } /** - * This method which generates a new Assessment from a landscape. + * This method generates a new Assessment from a landscape. * * @param landscape used to generate the new Assessment with its own kpis. * @return Assessment @@ -29,7 +29,7 @@ public static Assessment createAssessment(@NonNull Landscape landscape) { } /** - * This method which generates a new from a landscape and a kpi. + * This method generates a new Assessment from a landscape and a kpi. * * @param landscape used to generate the new Assessment. * @param kpis external kpi used to get status values. @@ -45,7 +45,7 @@ public static Assessment createAssessment(@NonNull Landscape landscape, @NonNull } /** - * This method which generates a new Assessment from map. + * This method generates a new Assessment from map. * * @param results used to generate the new Assessment with fully qualified identifier and a list of status values. * @return Assessment diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java index 5383def88..69ee2257c 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java @@ -24,6 +24,7 @@ public KPIFactory() { defaultKPIs.put(ScalingKPI.IDENTIFIER, ScalingKPI::new); defaultKPIs.put(ConditionKPI.IDENTIFIER, ConditionKPI::new); defaultKPIs.put(LifecycleKPI.IDENTIFIER, LifecycleKPI::new); + defaultKPIs.put(KubernetesKPI.IDENTIFIER, KubernetesKPI::new); } /** diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java new file mode 100644 index 000000000..6311f546c --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -0,0 +1,49 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.model.Component; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Labeled; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class KubernetesKPI implements KPI { + public static final String IDENTIFIER = "k8s"; + + + @Override + public List getStatusValues(Component component) { + if (!(component instanceof Labeled)) + return new ArrayList<>(); + + var status = Status.UNKNOWN; + var statusList = new ArrayList(); + var id = 1; + for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { + String key = entry.getKey(); + String flag = entry.getValue(); + if (StringUtils.isEmpty(flag)) + continue; + if (key.startsWith("condition.")) { + var message = key.replaceFirst("condition.", ""); + statusList.add(new StatusValue(IDENTIFIER + ":" + id++, Status.from(flag), message)); + } + } + return statusList; + + } + + @Override + public String getDescription() { + return "Evaluates Kubernetes conditions"; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java index 41afc6fde..540880056 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -1,24 +1,49 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.input.ItemType; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.client.KubernetesClient; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; public class DeploymentItem extends Item { - private Deployment deployment; + private final Deployment deployment; - public void setDeployment(Deployment deployment) { + public DeploymentItem(String name, String uid, String type, Deployment deployment) { + super(name, uid, type); this.deployment = deployment; } - public Deployment getDeployment() { - return deployment; - } - @Override public HasMetadata getWrappedItem() { return deployment; } + @Override + public Map getStatus() { + return super.getStatus().entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + pair -> { + if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { + return Status.GREEN.toString(); + } else { + return Status.RED.toString(); + } + })); + } + public static List getDeploymentItems(KubernetesClient client) { + var deploymentList = client.apps().deployments().list().getItems(); + return deploymentList.stream().map(deployment -> { + var deploymentItem = new DeploymentItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, deployment); + deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); + return deploymentItem; + }).collect(Collectors.toList()); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 2ddd0c0c8..3dd254553 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -1,30 +1,36 @@ package de.bonndan.nivio.input.kubernetes; import de.bonndan.nivio.input.InputFormatHandler; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.model.Label; -import de.bonndan.nivio.model.RelationType; import de.bonndan.nivio.observation.InputFormatObserver; -import de.bonndan.nivio.util.URLHelper; -import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.PersistentVolume; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; -import org.springframework.util.StringUtils; -import java.net.MalformedURLException; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; +import static de.bonndan.nivio.input.kubernetes.DeploymentItem.getDeploymentItems; +import static de.bonndan.nivio.input.kubernetes.PersistentVolumeClaimItem.getPersistentVolumeClaimItems; +import static de.bonndan.nivio.input.kubernetes.PersistentVolumeItem.getPersistentVolumeItems; +import static de.bonndan.nivio.input.kubernetes.PodItem.getPodItems; +import static de.bonndan.nivio.input.kubernetes.ReplicaSetItem.getReplicaSetItems; +import static de.bonndan.nivio.input.kubernetes.ServiceItem.getServiceItems; +import static de.bonndan.nivio.input.kubernetes.StatefulSetItem.getStatefulSetItems; + /** * Scans the k8s api for services, pods, volumes etc. */ @@ -34,16 +40,7 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { private static final Logger LOGGER = LoggerFactory.getLogger(InputFormatHandlerKubernetes.class); public static final String NAMESPACE = "namespace"; - public static final String GROUP_LABEL_PARAM = "groupLabel"; - /** - * label name to determine the group name (fallback from GROUP_LABEL) - */ - public static final String APP_KUBERNETES_IO_INSTANCE_LABEL = "app.kubernetes.io/instance"; - public static final String APP_SELECTOR = "app"; - - private String namespace = null; - private String groupLabel = null; private KubernetesClient client; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @@ -62,58 +59,30 @@ public List getFormats() { @Override public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { - try { - if (!StringUtils.isEmpty(reference.getUrl())) { - URL url = new URL(reference.getUrl()); - Map params = URLHelper.splitQuery(url); - if (params.containsKey(NAMESPACE)) { - namespace = params.get(NAMESPACE); - } - if (params.containsKey(GROUP_LABEL_PARAM)) { - this.groupLabel = params.get(GROUP_LABEL_PARAM); - } - } - } catch (MalformedURLException ignored) { - } + this.client = getClient(reference.getUrl()); - KubernetesClient client = getClient(reference.getUrl()); + var persistentVolumeClaims = getPersistentVolumeClaimItems(client); + var persistentVolumes = getPersistentVolumeItems(client); + crossReferenceClaimer(persistentVolumeClaims, persistentVolumes); - List descriptions = new ArrayList<>(); - final List pods = new ArrayList<>(); - getPods().forEach(pod -> { - ItemDescription podItem = createPodItemDescription(pod); - descriptions.add(podItem); - pods.add(podItem); - List descriptionsFromPod = createDescriptionsFromPod(pod, podItem); - descriptions.addAll(descriptionsFromPod); - }); - - List services = client.services().list().getItems(); - List itemServices = new ArrayList<>(); - LOGGER.info("Found services: {}", services.stream().map(service -> service.getMetadata().getName()).collect(Collectors.toList())); - services.stream() - .filter(service -> namespace == null || namespace.equals(service.getMetadata().getNamespace())) - .forEach(service -> itemServices.add(createDescriptionFromService(service, pods))); + var itemList = getK8sComponents(client); + crossReferenceOwner(itemList); - descriptions.addAll(itemServices); - //landscapeDescription.mergeItems(descriptions); + itemList.addAll(persistentVolumeClaims); + itemList.addAll(persistentVolumes); - var deployments = getDeployments(client); - var replicaSets = getReplicaSets(client); - var podList = getPodItems(); - var serviceList = getServiceItems(client); - var statefulSets = getStatefulSet(client); + landscapeDescription.mergeItems(createItemDescription(itemList)); + } + private ArrayList getK8sComponents(KubernetesClient client) { var itemList = new ArrayList(); - itemList.addAll(deployments); - itemList.addAll(replicaSets); - itemList.addAll(podList); - itemList.addAll(serviceList); - itemList.addAll(statefulSets); - crossReferenceOwner(itemList); - var e = createItemDescription(itemList); - landscapeDescription.mergeItems(e); + itemList.addAll(getDeploymentItems(client)); + itemList.addAll(getReplicaSetItems(client)); + itemList.addAll(getPodItems(client)); + itemList.addAll(getServiceItems(client)); + itemList.addAll(getStatefulSetItems(client)); + return itemList; } private List createItemDescription(List itemList) { @@ -142,65 +111,11 @@ private void crossReferenceOwner(ArrayList items) { }); } - private List getPodItems() { - var pods = getPods(); - return pods.stream().map(pod -> { - var podItem = new PodItem(); - podItem.setType(ItemType.POD); - podItem.setPod(pod); - podItem.setName(pod.getMetadata().getName()); - podItem.setUid(pod.getMetadata().getUid()); - return podItem; - }).collect(Collectors.toList()); - } - - private List getDeployments(KubernetesClient client) { - var deploymentList = client.apps().deployments().list().getItems(); - return deploymentList.stream().map(deployment -> { - var deploymentItem = new DeploymentItem(); - deploymentItem.setType(ItemType.DEPLOYMENT); - deploymentItem.setDeployment(deployment); - deploymentItem.setName(deployment.getMetadata().getName()); - deploymentItem.setUid(deployment.getMetadata().getUid()); - deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); - return deploymentItem; - }).collect(Collectors.toList()); - } - - private List getReplicaSets(KubernetesClient client) { - var replicaSetList = client.apps().replicaSets().list().getItems(); - return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new ReplicaSetItem(); - replicaSetItem.setType(ItemType.REPLICASET); - replicaSetItem.setReplicaSet(replicaSet); - replicaSetItem.setName(replicaSet.getMetadata().getName()); - replicaSetItem.setUid(replicaSet.getMetadata().getUid()); - return replicaSetItem; - }).collect(Collectors.toList()); - } - - private List getServiceItems(KubernetesClient client) { - var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> { - var serviceItem = new ServiceItem(); - serviceItem.setType(ItemType.SERVICE); - serviceItem.setService(service); - serviceItem.setName(service.getMetadata().getName()); - serviceItem.setUid(service.getMetadata().getUid()); - return serviceItem; - }).collect(Collectors.toList()); - } - - private List getStatefulSet(KubernetesClient client) { - var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> { - var statefulSetItem = new StatefulSetItem(); - statefulSetItem.setType(ItemType.STATEFULSET); - statefulSetItem.setStatefulSet(statefulSet); - statefulSetItem.setName(statefulSet.getMetadata().getName()); - statefulSetItem.setUid(statefulSet.getMetadata().getUid()); - return statefulSetItem; - }).collect(Collectors.toList()); + private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { + persistentVolumes.forEach(item -> { + var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) item.getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); + item.setOwners(new ArrayList<>(claimer)); + }); } @Override @@ -208,169 +123,18 @@ public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, return null; } - /** - * Creates a pod item - * - * @param pod k8s pod object - * @return pod (yet ungrouped) - */ - private ItemDescription createPodItemDescription(Pod pod) { - ItemDescription itemDescription = new ItemDescription(); - itemDescription.setName(pod.getMetadata().getName()); - itemDescription.setIdentifier(pod.getMetadata().getName()); - itemDescription.setType(ItemType.POD); - itemDescription.setGroup(getGroup(pod)); - pod.getMetadata().getLabels().forEach(itemDescription::setLabel); - return itemDescription; - } - - /** - * @return all pods in the namespace - */ - private List getPods() { - try { - List pods = client.pods().list().getItems(); - LOGGER.info("Found pods: {}", pods.stream().map(pod -> pod.getMetadata().getName()).collect(Collectors.toList())); - return pods.stream() - .filter(pod -> namespace == null || namespace.equals(pod.getMetadata().getNamespace())) - .collect(Collectors.toList()); - } catch (Exception ex) { - throw new ProcessingException("Failed to load pods ", ex); - } - } - - private ItemDescription createDescriptionFromService(Service kubernetesService, List pods) { - - ItemDescription service = new ItemDescription(); - service.setIdentifier(kubernetesService.getMetadata().getName()); - service.setType(ItemType.SERVICE); - - String group = getGroup(kubernetesService); - service.setGroup(group); - - //link pods as providers - pods.stream() - .filter(pod -> pod.getName().startsWith(service.getIdentifier())) - .forEach(pod -> { - RelationDescription rel = new RelationDescription(pod.getIdentifier(), service.getIdentifier()); - rel.setType(RelationType.PROVIDER); - service.addRelation(rel); - pod.setGroup(service.getGroup()); - }); - - return service; - } - - public Config getConfiguration() { - return getClient("").getConfiguration(); - } - - private List createDescriptionsFromPod(Pod pod, ItemDescription podItem) { - - List descriptions = new ArrayList<>(); - - ItemDescription node = new ItemDescription(); - node.setName(pod.getSpec().getNodeName()); - node.setIdentifier(pod.getSpec().getNodeName()); - node.setType(ItemType.SERVER); - descriptions.add(node); - podItem.addRelation(new RelationDescription(node.getIdentifier(), podItem.getIdentifier())); - - String group = getGroup(pod); - pod.getSpec().getContainers().forEach(container -> { - ItemDescription containerDesc = new ItemDescription(); - containerDesc.setGroup(group); - containerDesc.setName(container.getName()); - containerDesc.setIdentifier(podItem.getName() + "-" + container.getName()); - containerDesc.setLabel(Label.software, container.getImage()); - containerDesc.setType(ItemType.CONTAINER); - pod.getMetadata().getLabels().forEach(containerDesc::setLabel); - - //container provides the pod - RelationDescription relationDescription = new RelationDescription(containerDesc.getIdentifier(), podItem.getIdentifier()); - relationDescription.setType(RelationType.PROVIDER); - containerDesc.addRelation(relationDescription); - - // TODO - //description.setScale(...); - // statuses: pod.getStatus() - setConditionsAndHealth(pod.getStatus(), podItem); - podItem.setLabel("hostIP", pod.getStatus().getHostIP()); - podItem.setLabel("podIP", pod.getStatus().getPodIP()); - podItem.setLabel("phase", pod.getStatus().getPhase()); - podItem.setLabel("startTime", pod.getStatus().getStartTime()); - //description.setNetworks(); - - descriptions.add(containerDesc); - }); - - pod.getSpec().getVolumes().forEach(volume -> { - - //storing configmap volumes in labels - if (volume.getConfigMap() != null) { - podItem.setLabel(Label.withPrefix("configMap", volume.getConfigMap().getName()), volume.getConfigMap().getName()); - return; - } - - ItemDescription volumeDesc = createVolumeDescription(group, volume, pod, podItem); - descriptions.add(volumeDesc); - }); - - return descriptions; - } - - private ItemDescription createVolumeDescription(String group, Volume volume, Pod pod, ItemDescription podItem) { - ItemDescription volumeDesc = new ItemDescription(); - volumeDesc.setGroup(group); - volumeDesc.setName(volume.getName()); - volumeDesc.setIdentifier(podItem.getName() + "-" + volume.getName()); - volumeDesc.setType(ItemType.VOLUME); - if (volume.getSecret() != null && volume.getSecret().getSecretName().equals(volume.getName())) { - volumeDesc.setLabel("secret", 1); - volumeDesc.setType(ItemType.SECRET); - } - pod.getMetadata().getLabels().forEach(volumeDesc::setLabel); - - //volume provides the pod - RelationDescription relationDescription = new RelationDescription(volumeDesc.getIdentifier(), podItem.getIdentifier()); - relationDescription.setType(RelationType.PROVIDER); - volumeDesc.addRelation(relationDescription); - - return volumeDesc; - } - - private void setConditionsAndHealth(PodStatus status, ItemDescription podItem) { - if (status != null && status.getConditions() != null) { - status.getConditions().forEach(podCondition -> { - podItem.setLabel(Label.condition.withPrefix(podCondition.getType()), podCondition.getStatus()); - }); - } - } - - private String getGroup(HasMetadata hasMetadata) { - if (groupLabel != null) { - String labelValue = hasMetadata.getMetadata().getLabels().getOrDefault(groupLabel, ""); - if (!StringUtils.isEmpty(labelValue)) { - return labelValue; - } - } - - String labelValue = hasMetadata.getMetadata().getLabels().getOrDefault(APP_KUBERNETES_IO_INSTANCE_LABEL, ""); - if (!StringUtils.isEmpty(labelValue)) { - return labelValue; - } - - return ""; - } - private KubernetesClient getClient(String context) { if (this.client != null) return this.client; // see https://github.com/fabric8io/kubernetes-client#configuring-the-client - Config config = Config.autoConfigure(context); + var config = Config.autoConfigure(context); this.client = new DefaultKubernetesClient(config); return this.client; } + + public Config getConfiguration() { + return getClient("").getConfiguration(); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java index ed8781f0f..2f0aec59a 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -9,40 +9,31 @@ import java.util.Map; public abstract class Item { - protected String name; - private String uid; - private String type; + private final String name; - private final Map status = new HashMap<>(); - - private final List owners = new ArrayList<>(); + private List owners = new ArrayList<>(); private final List relationDescriptionList = new ArrayList<>(); + private final Map status = new HashMap<>(); + private final String type; + private final String uid; - public List getRelationDescriptionList() { - return relationDescriptionList; - } - - public Map getStatus() { - return status; - } - - public void addStatus(String key, String value) { - status.put(key, value); + protected Item(String name, String uid, String type) { + this.name = name; + this.uid = uid; + this.type = type; } - public abstract HasMetadata getWrappedItem(); - - public String getType() { - return type; + public void addOwner(Item owner) { + this.owners.add(owner); } - public void setType(String type) { - this.type = type; + public void addRelation(RelationDescription relationDescription) { + relationDescriptionList.add(relationDescription); } - public String getName() { - return name; + public void addStatus(String key, String value) { + status.put(key, value); } public String getGroup() { @@ -53,31 +44,33 @@ public String getGroup() { } } - public void setName(String name) { - this.name = name; + public String getName() { + return name; } public List getOwner() { return owners; } - public void addOwner(Item owner) { - this.owners.add(owner); + public List getRelationDescriptionList() { + return relationDescriptionList; } - public void setOwners(List owners) { - this.owners.addAll(owners); + public Map getStatus() { + return status; } - public void addRelation(RelationDescription relationDescription) { - relationDescriptionList.add(relationDescription); + public String getType() { + return type; } public String getUid() { return uid; } - public void setUid(String uid) { - this.uid = uid; + public abstract HasMetadata getWrappedItem(); + + public void setOwners(List owners) { + this.owners = owners; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java new file mode 100644 index 000000000..e9f67c0c2 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java @@ -0,0 +1,28 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; +import io.fabric8.kubernetes.client.KubernetesClient; + +import java.util.List; +import java.util.stream.Collectors; + +public class PersistentVolumeClaimItem extends Item { + private final PersistentVolumeClaim persistentVolumeClaim; + + protected PersistentVolumeClaimItem(String name, String uid, String type, PersistentVolumeClaim persistentVolumeClaim) { + super(name, uid, type); + this.persistentVolumeClaim = persistentVolumeClaim; + } + + @Override + public HasMetadata getWrappedItem() { + return persistentVolumeClaim; + } + + public static List getPersistentVolumeClaimItems(KubernetesClient client) { + var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new PersistentVolumeClaimItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java new file mode 100644 index 000000000..0d5deb821 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java @@ -0,0 +1,28 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.client.KubernetesClient; + +import java.util.List; +import java.util.stream.Collectors; + +public class PersistentVolumeItem extends Item { + private final PersistentVolume persistentVolume; + + protected PersistentVolumeItem(String name, String uid, String type, PersistentVolume persistentVolume) { + super(name, uid, type); + this.persistentVolume = persistentVolume; + } + + @Override + public HasMetadata getWrappedItem() { + return persistentVolume; + } + + public static List getPersistentVolumeItems(KubernetesClient client) { + var getPersistentVolumeList = client.persistentVolumes().list().getItems(); + return getPersistentVolumeList.stream().map(persistentVolumeClaims -> new PersistentVolumeItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java index 976dd4fcf..a8b485d16 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -1,16 +1,21 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.input.ItemType; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.client.KubernetesClient; -public class PodItem extends Item { - Pod pod; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; - public Pod getPod() { - return pod; - } +public class PodItem extends Item { + private final Pod pod; - public void setPod(Pod pod) { + protected PodItem(String name, String uid, String type, Pod pod) { + super(name, uid, type); this.pod = pod; } @@ -18,4 +23,26 @@ public void setPod(Pod pod) { public HasMetadata getWrappedItem() { return pod; } + + @Override + public Map getStatus() { + return super.getStatus().entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + pair -> { + if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { + return Status.GREEN.toString(); + } else { + return Status.RED.toString(); + } + })); + } + + public static List getPodItems(KubernetesClient client) { + var pods = client.pods().list().getItems(); + return pods.stream().map(pod -> { + var podItem = new PodItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, pod); + pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); + return podItem; + }).collect(Collectors.toList()); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java index b5f926be2..602078966 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -1,34 +1,50 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.input.ItemType; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.ReplicaSet; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.apache.commons.collections.map.SingletonMap; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; public class ReplicaSetItem extends Item { - ReplicaSet replicaSet; - List serviceItems; + private final ReplicaSet replicaSet; - - public ReplicaSet getReplicaSet() { - return replicaSet; - } - - public void setReplicaSet(ReplicaSet replicaSet) { + protected ReplicaSetItem(String name, String uid, String type, ReplicaSet replicaSet) { + super(name, uid, type); this.replicaSet = replicaSet; } - public List getServiceItems() { - return serviceItems; + @Override + public HasMetadata getWrappedItem() { + return replicaSet; } - public void setServiceItems(List serviceItems) { - this.serviceItems = serviceItems; + @Override + public Map getStatus() { + var replicaCount = replicaSet.getSpec().getReplicas(); + var replicaCountDesired = Integer.valueOf(replicaSet.getMetadata().getAnnotations().get("deployment.kubernetes.io/desired-replicas")); + var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); + if (Objects.equals(replicaCount, replicaCountDesired)) { + return new SingletonMap(message, Status.GREEN.toString()); + } else if (replicaCount == 0) { + return new SingletonMap(message, Status.RED.toString()); + } else + return new SingletonMap(message, Status.ORANGE.toString()); } - @Override - public HasMetadata getWrappedItem() { - return replicaSet; + public static List getReplicaSetItems(KubernetesClient client) { + var replicaSetList = client.apps().replicaSets().list().getItems(); + return replicaSetList.stream().map(replicaSet -> { + var replicaSetItem = new ReplicaSetItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, replicaSet); + replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); + return replicaSetItem; + }).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java index d937ef094..6d2cc2265 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -1,16 +1,18 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.input.ItemType; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; -public class ServiceItem extends Item { - Service service; +import java.util.List; +import java.util.stream.Collectors; - public Service getService() { - return service; - } +public class ServiceItem extends Item { + private final Service service; - public void setService(Service service) { + protected ServiceItem(String name, String uid, String type, Service service) { + super(name, uid, type); this.service = service; } @@ -18,4 +20,9 @@ public void setService(Service service) { public HasMetadata getWrappedItem() { return service; } + + public static List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> new ServiceItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, service)).collect(Collectors.toList()); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java index 2eb5101f5..ae25cea7c 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -1,16 +1,18 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.input.ItemType; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.client.KubernetesClient; -public class StatefulSetItem extends Item { - private StatefulSet statefulSet; +import java.util.List; +import java.util.stream.Collectors; - public StatefulSet getStatefulSet() { - return statefulSet; - } +public class StatefulSetItem extends Item { + private final StatefulSet statefulSet; - public void setStatefulSet(StatefulSet statefulSet) { + protected StatefulSetItem(String name, String uid, String type, StatefulSet statefulSet) { + super(name, uid, type); this.statefulSet = statefulSet; } @@ -18,4 +20,9 @@ public void setStatefulSet(StatefulSet statefulSet) { public HasMetadata getWrappedItem() { return statefulSet; } + + public static List getStatefulSetItems(KubernetesClient client) { + var statefulSetList = client.apps().statefulSets().list().getItems(); + return statefulSetList.stream().map(statefulSet -> new StatefulSetItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, statefulSet)).collect(Collectors.toList()); + } } diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java index a74c31f39..5a36cdb50 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java @@ -1,11 +1,11 @@ package de.bonndan.nivio.assessment.kpi; -import de.bonndan.nivio.model.LandscapeConfig; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.input.ProcessLog; -import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeConfig; +import de.bonndan.nivio.model.LandscapeFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -14,7 +14,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; class KPIFactoryTest { @@ -39,7 +39,7 @@ public void defaultKPIs() { Map configuredKPIs = kpiFactory.getConfiguredKPIs(landscapeConfig.getKPIs()); assertNotNull(configuredKPIs); - assertEquals(4, configuredKPIs.size()); + assertEquals(5, configuredKPIs.size()); assertTrue(configuredKPIs.get(ScalingKPI.IDENTIFIER) instanceof ScalingKPI); } diff --git a/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java index 65a8ee15d..e0b374c2f 100644 --- a/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; class ComponentDescriptionValuesTest { diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java new file mode 100644 index 000000000..de83994a3 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java @@ -0,0 +1,18 @@ +package de.bonndan.nivio.input.kubernetes; + +import org.junit.jupiter.api.Test; + +class DeploymentItemTest { + + @Test + void getWrappedItem() { + } + + @Test + void getStatus() { + } + + @Test + void getDeploymentItems() { + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java similarity index 94% rename from src/test/java/de/bonndan/nivio/input/KubernetesTest.java rename to src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java index 6a99eb04c..5b1b4ddb8 100644 --- a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java @@ -1,9 +1,9 @@ -package de.bonndan.nivio.input; +package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.input.ItemType; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.PodSpecBuilder; @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@EnableKubernetesMockClient(crud = true, https = false) +@EnableKubernetesMockClient(crud = true) public class KubernetesTest { static KubernetesClient client; diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java new file mode 100644 index 000000000..ba652d754 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java @@ -0,0 +1,78 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@EnableKubernetesMockClient(crud = true, https = false) +class PersistentVolumeClaimItemTest { + PersistentVolumeClaim persistentVolumeClaim; + PersistentVolumeClaimItem persistentVolumeClaimItem; + KubernetesMockServer kubernetesMockServer = new KubernetesMockServer(); + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + persistentVolumeClaim = new PersistentVolumeClaimBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("default") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new PersistentVolumeClaimSpecBuilder() + .withVolumeName("test") + .build()) + .withStatus(new PersistentVolumeClaimStatusBuilder() + .build()) + .build(); + persistentVolumeClaimItem = new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim); + kubernetesClient.persistentVolumeClaims().inNamespace("default").create(persistentVolumeClaim); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = persistentVolumeClaimItem.getWrappedItem(); + assertThat(result).isEqualTo(persistentVolumeClaim); + } + + @Test + void testGetPersistentVolumeClaimItems() { + + var test = kubernetesClient.persistentVolumeClaims().list().getItems(); + List result = PersistentVolumeClaimItem.getPersistentVolumeClaimItems(kubernetesClient); + assertThat(Collections.singletonList(new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim))).isEqualTo(result); + } + + @Test + void testAddOwner() { + persistentVolumeClaimItem.addOwner(null); + } + + @Test + void testAddRelation() { + persistentVolumeClaimItem.addRelation(new RelationDescription("source", "target")); + } + + @Test + void testAddStatus() { + persistentVolumeClaimItem.addStatus("key", "value"); + } + + @Test + void testGetGroup() { + String result = persistentVolumeClaimItem.getGroup(); + Assertions.assertEquals("replaceMeWithExpectedResult", result); + } +} diff --git a/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java b/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java index b1efea084..fc48f24f9 100644 --- a/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java @@ -12,7 +12,8 @@ import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; class LandscapeFactoryTest { @@ -99,7 +100,7 @@ void fromInputAddsKPIs() { Landscape landscape = LandscapeFactory.createFromInput(description); assertThat(landscape.getKpis()).isNotEmpty(); - assertThat(landscape.getKpis()).hasSize(4); + assertThat(landscape.getKpis()).hasSize(5); } @Test @@ -117,6 +118,6 @@ void recreateAddsKPIs() { Landscape landscape = LandscapeFactory.recreate(existing, description); assertThat(landscape.getKpis()).isNotEmpty(); - assertThat(landscape.getKpis()).hasSize(4); + assertThat(landscape.getKpis()).hasSize(5); } } \ No newline at end of file From 1c423736da876a8280910204caf8e6a2af31426d Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 13:26:40 +0200 Subject: [PATCH 077/310] [#563] RangeApiModel with description --- .../nivio/assessment/kpi/RangeApiModel.java | 19 +++++++++++++++++++ .../nivio/assessment/kpi/ScalingKPI.java | 8 ++++---- .../bonndan/nivio/model/LandscapeConfig.java | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java b/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java index 38f522108..b074e5c17 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/RangeApiModel.java @@ -1,23 +1,42 @@ package de.bonndan.nivio.assessment.kpi; +import com.fasterxml.jackson.annotation.JsonInclude; import org.apache.commons.lang3.Range; import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import java.util.Objects; +@JsonInclude(JsonInclude.Include.NON_NULL) public class RangeApiModel { + @NonNull private final Range range; + @Nullable + private final String description; + public RangeApiModel(@NonNull final Range range) { + this(range, null); + } + + public RangeApiModel(@NonNull final Range range, @Nullable final String description) { this.range = Objects.requireNonNull(range, "Non null range is required"); + this.description = description; } + @NonNull public String getMinimum() { return range.getMinimum().toString(); } + @NonNull public String getMaximum() { return range.getMaximum().toString(); } + + @Nullable + public String getDescription() { + return description; + } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java index 61fcc737e..ab5a73239 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java @@ -35,14 +35,14 @@ public class ScalingKPI extends AbstractKPI { private final Map ranges = Map.of( Status.GREEN, new RangeApiModel(Range.between(1D, Double.POSITIVE_INFINITY)), - Status.YELLOW, new RangeApiModel(Range.between(0D, 0D)), - Status.ORANGE, new RangeApiModel(Range.between(0D, 0D)), - Status.RED, new RangeApiModel(Range.between(0D, 0D)) + Status.YELLOW, new RangeApiModel(Range.between(0D, 0D), SCALED_TO_ZERO), + Status.ORANGE, new RangeApiModel(Range.between(0D, 0D), "data sink scaled to zero"), + Status.RED, new RangeApiModel(Range.between(0D, 0D), "provider scaled to zero") ); @Override public String getDescription() { - return "Turns yellow if the 'scale' label is zero. Turns orange or red if is also is a data sink or provider."; + return "Turns yellow if the 'scale' label is zero. Turns orange or red if it is also is a data sink or provider."; } @NonNull diff --git a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java index fda6e439a..e169a8f92 100644 --- a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java +++ b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java @@ -135,12 +135,12 @@ public void setMaxDistanceLimitFactor(Float maxDistanceLimitFactor) { } } + /** * The configured KPIs. * * @return all active {@link AbstractKPI}s with their unique identifier */ - @JsonIgnore public Map getKPIs() { return kpis; } From 3ba62112f5812efb52048cc2551bb1f246c0da05 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 13:27:34 +0200 Subject: [PATCH 078/310] [#563] showing konfigured kpis --- .../Dashboard/KPIConfigLayout.test.tsx | 48 +++++++++ .../Landscape/Dashboard/KPIConfigLayout.tsx | 97 +++++++++++++++++++ .../Landscape/Dashboard/StatusBar.test.tsx | 2 +- .../Landscape/Dashboard/StatusBarLayout.tsx | 28 +++--- src/main/app/src/interfaces.ts | 10 +- 5 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx create mode 100644 src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx diff --git a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx new file mode 100644 index 000000000..96fc8a5cc --- /dev/null +++ b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx @@ -0,0 +1,48 @@ +import { render } from '@testing-library/react'; +import React from 'react'; +import KPIConfigLayout from './KPIConfigLayout'; +import { IKpi } from "../../../interfaces"; + +describe('', () => { + + const kpi: IKpi = { + "description": "Turns yellow if the 'scale' label is zero. Turns orange or red if is also is a data sink or provider.", + "enabled": true, + "ranges": { + "GREEN": { + "maximum": "Infinity", + "minimum": "1.0" + }, + "YELLOW": { + "description": "scaled to zero", + "maximum": "0.0", + "minimum": "0.0" + }, + "ORANGE": { + "description": "data sink scaled to zero", + "maximum": "0.0", + "minimum": "0.0" + }, + "RED": { + "description": "provider scaled to zero", + "maximum": "0.0", + "minimum": "0.0" + } + }, + "matches": { + "GREEN": [ + "All conditions are met." + ], + "RED": [ + "One condition is not met." + ] + } + }; + + it('should display', () => { + const { getByText, queryByText } = render(); + expect(getByText('fooKPI')).toBeInTheDocument(); + expect(getByText('All conditions are met.')).toBeInTheDocument(); + expect(getByText('[1.0 → Infinity]')).toBeInTheDocument(); + }); +}); diff --git a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx new file mode 100644 index 000000000..decada224 --- /dev/null +++ b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { IKpi } from '../../../interfaces'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Table, + TableBody, + TableCell, + TableRow, +} from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import StatusChip from '../../StatusChip/StatusChip'; +import { ExpandMore } from '@material-ui/icons'; + +interface Props { + name: string; + kpi: IKpi; +} + +/** + * Displays the configuration of a single KPI. + * + * @param name kpi name + * @param kpi + * @constructor + */ +const KPIConfigLayout: React.FC = ({ name, kpi }) => { + let ranges: JSX.Element[] = []; + if (kpi.ranges) { + for (let key of Object.keys(kpi.ranges)) { + const range = kpi.ranges[key]; + const rangeText = + range.minimum == range.maximum ? range.minimum : `${range.minimum} → ${range.maximum}`; + ranges.push( + + + + + + + {`[${rangeText}]`} {range.description ?? ''} + + + + ); + } + } + let matches: JSX.Element[] = []; + if (kpi.matches) { + for (let key of Object.keys(kpi.matches)) { + const matchers = kpi.matches[key]; + matches.push( + + + + + + {matchers.join(', ')} + + + ); + } + } + + return ( + + + } + aria-controls={'panel_kpi' + name + 'bh-content'} + id={'panel_kpi' + name + 'bh-header'} + > + {name} + + +
{kpi.description}
+
+ + {ranges.length ? ( + + {ranges} +
+ ) : null} + {matches.length ? ( + + {matches} +
+ ) : null} +
+
+
+ ); +}; +export default KPIConfigLayout; diff --git a/src/main/app/src/Components/Landscape/Dashboard/StatusBar.test.tsx b/src/main/app/src/Components/Landscape/Dashboard/StatusBar.test.tsx index 8eff5c20c..59d3014e6 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/StatusBar.test.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/StatusBar.test.tsx @@ -12,7 +12,7 @@ describe('', () => { {}} onGroupClick={() => {}} /> ); - expect(getByText('Warnings')).toBeInTheDocument(); + expect(getByText('Status')).toBeInTheDocument(); }); it('should display an assessment', () => { diff --git a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx index e99d2975f..d192ff4d1 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx @@ -4,7 +4,6 @@ import StatusChip from '../../StatusChip/StatusChip'; import Button from '@material-ui/core/Button'; import { AppBar, - Box, Card, CardHeader, Tab, @@ -22,7 +21,7 @@ import ItemAvatar from '../Modals/Item/ItemAvatar'; import GroupAvatar from '../Modals/Group/GroupAvatar'; import { a11yProps, TabPanel } from '../Utils/TabUtils'; import CardContent from '@material-ui/core/CardContent'; -import Typography from '@material-ui/core/Typography'; +import KPIConfigLayout from './KPIConfigLayout'; interface Props { onItemClick: Function; @@ -125,24 +124,20 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { if (!visible) return null; const kpiConfig = context.landscape?.kpis; - let kpis : JSX.Element[] = []; + let kpis: JSX.Element[] = []; if (kpiConfig) { - for (let key of Object.keys(kpiConfig)) - { - const kpi = kpiConfig[key]; - kpis.push( - - {key} -

{kpi.description}

-
- ) + for (let key of Object.keys(kpiConfig)) { + const kpiConfigElement = kpiConfig[key]; + if (kpiConfigElement.enabled) { + kpis.push(); + } } } return ( { @@ -154,7 +149,12 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { } /> - + } label={'warnings'} diff --git a/src/main/app/src/interfaces.ts b/src/main/app/src/interfaces.ts index 39fa82be7..02343725d 100644 --- a/src/main/app/src/interfaces.ts +++ b/src/main/app/src/interfaces.ts @@ -54,11 +54,17 @@ export interface IKpi { } export interface IRanges { - [key: string]: string; + [key: string]: IRange; +} + +export interface IRange { + minimum: string; + maximum: string; + description?: string; } export interface IMatches { - [key: string]: string; + [key: string]: string[]; } export interface IBranding { From e9c8c03c98c76d0dcf26367dc6ea288cb29ca53c Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 14:07:02 +0200 Subject: [PATCH 079/310] [#563] cleanup --- .../app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx index decada224..4c7e123bb 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx @@ -32,7 +32,7 @@ const KPIConfigLayout: React.FC = ({ name, kpi }) => { for (let key of Object.keys(kpi.ranges)) { const range = kpi.ranges[key]; const rangeText = - range.minimum == range.maximum ? range.minimum : `${range.minimum} → ${range.maximum}`; + range.minimum === range.maximum ? range.minimum : `${range.minimum} → ${range.maximum}`; ranges.push( From b018b6bc9e10721530992c365c67bf92778f0af8 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 14:27:45 +0200 Subject: [PATCH 080/310] [#563] cleanup --- src/main/java/de/bonndan/nivio/model/LandscapeConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java index e169a8f92..b0bc51a4c 100644 --- a/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java +++ b/src/main/java/de/bonndan/nivio/model/LandscapeConfig.java @@ -1,6 +1,5 @@ package de.bonndan.nivio.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.assessment.kpi.KPIConfig; import io.swagger.v3.oas.annotations.media.Schema; From bdc98a4a330061ed32018b5f0eabf8eb4911d6e8 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 17:59:27 +0200 Subject: [PATCH 081/310] [#358] cleanup --- .../bonndan/nivio/input/external/github/GitHubProperties.java | 2 -- .../bonndan/nivio/input/external/gitlab/GitLabProperties.java | 1 - .../de/bonndan/nivio/input/external/sonar/SonarProperties.java | 2 -- 3 files changed, 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java index 54858449d..a80b8dbac 100644 --- a/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/github/GitHubProperties.java @@ -4,8 +4,6 @@ @ConfigurationProperties(prefix = "github") - - public class GitHubProperties { private String login; diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java index 35d7e28c2..e27736586 100644 --- a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -3,7 +3,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "gitlab") - public class GitLabProperties { private String hostUrl; diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java index c1902397c..91bdd45db 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -4,8 +4,6 @@ @ConfigurationProperties(prefix = "sonar") - - public class SonarProperties { private String serverUrl; From 852f0f80f27670dacfc70fd45e4abe04105385b0 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 6 Jul 2021 18:06:46 +0200 Subject: [PATCH 082/310] [#358] cleanup --- application.yml | 13 ------------- .../de/bonndan/nivio/config/SeedProperties.java | 3 --- .../de/bonndan/nivio/input/StartupListener.java | 6 ++---- 3 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 application.yml diff --git a/application.yml b/application.yml deleted file mode 100644 index 85b0c270b..000000000 --- a/application.yml +++ /dev/null @@ -1,13 +0,0 @@ -spring: - application: - name: nivio - main: - lazy-initialization: true - -github: # add new environment variables - login: kohsuke - password: 012345678 - oauth: 4d98173f7c075527cb64878561d1fe70 - jwt: my_jwt_token - - diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index 52f9ac65c..6089848a3 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -2,9 +2,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; - @ConfigurationProperties(prefix = "nivio") - public class SeedProperties { private String seed; @@ -16,5 +14,4 @@ public String getSeed() { public void setSeed(String seed) { this.seed = seed; } - } diff --git a/src/main/java/de/bonndan/nivio/input/StartupListener.java b/src/main/java/de/bonndan/nivio/input/StartupListener.java index ca266a543..e82011026 100644 --- a/src/main/java/de/bonndan/nivio/input/StartupListener.java +++ b/src/main/java/de/bonndan/nivio/input/StartupListener.java @@ -1,20 +1,18 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.config.ConfigurableEnvVars; -import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationListener; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; -import java.util.Optional; /** * After the application has booted the SEED ({@link Seed}) is processed. @@ -38,7 +36,7 @@ public StartupListener(LandscapeDescriptionFactory landscapeDescriptionFactory, } @Override - public void onApplicationEvent(final ApplicationReadyEvent event) { + public void onApplicationEvent(@NonNull final ApplicationReadyEvent event) { if (!StringUtils.isEmpty(ConfigurableEnvVars.DEMO.value().orElse(""))) { LOGGER.info("Running in demo mode"); } From d6d90bcb0a8a3a37af0125724493d11426b313df Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 8 Jul 2021 03:56:34 +0000 Subject: [PATCH 083/310] fix: upgrade typescript from 3.9.9 to 3.9.10 Snyk has created this PR to upgrade typescript from 3.9.9 to 3.9.10. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index caa5803da..383ce441e 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -30,7 +30,7 @@ "react-svg-pan-zoom-loader": "^1.4.1", "react-transition-group": "^4.4.2", "svg-path-properties": "^1.0.10", - "typescript": "~3.9.9" + "typescript": "~3.9.10" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.1", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 57538f86d..1c974519f 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -11865,10 +11865,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@~3.9.9: - version "3.9.9" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674" - integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w== +typescript@~3.9.10: + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== unbox-primitive@^1.0.0: version "1.0.0" From 8e68089a001604ea526eb52050fbdffe3152f6bc Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:02:31 +0200 Subject: [PATCH 084/310] add the variable seedProperties and modifies the constructor and the method trigger() --- .../java/de/bonndan/nivio/input/demo/ChangeTrigger.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java index a8f1e71f0..8ed5a1057 100644 --- a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java +++ b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input.demo; import de.bonndan.nivio.config.ConfigurableEnvVars; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.input.IndexEvent; import de.bonndan.nivio.input.LandscapeDescriptionFactory; import de.bonndan.nivio.input.dto.LandscapeDescription; @@ -21,18 +22,21 @@ public class ChangeTrigger { private final LandscapeDescriptionFactory landscapeDescriptionFactory; private final ApplicationEventPublisher eventPublisher; + private final SeedProperties seedProperties; public ChangeTrigger(LandscapeDescriptionFactory landscapeDescriptionFactory, - ApplicationEventPublisher eventPublisher + ApplicationEventPublisher eventPublisher, + SeedProperties seedProperties ) { this.landscapeDescriptionFactory = landscapeDescriptionFactory; this.eventPublisher = eventPublisher; + this.seedProperties = seedProperties; } @Scheduled(initialDelay = 20000, fixedDelay = 30000) public void trigger() { - if (ConfigurableEnvVars.DEMO.value().isEmpty()) { + if (seedProperties.getSeed().isEmpty()) { LOGGER.debug("DEMO not set, not simulating any pet clinic events."); return; } From aed618ab61ef53870e80d2c5eb891d9fa3487ff1 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:05:12 +0200 Subject: [PATCH 085/310] add the variable seedProperties and modify the method setUp() --- .../java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java index 242fa9dec..5ce29a905 100644 --- a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java +++ b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.demo; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.input.LandscapeDescriptionFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,12 +14,14 @@ class ChangeTriggerTest { private LandscapeDescriptionFactory factory; private ApplicationEventPublisher publisher; private ChangeTrigger trigger; + private SeedProperties seedProperties; @BeforeEach void setUp() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - trigger = new ChangeTrigger(factory, publisher); + seedProperties = mock(SeedProperties.class); + trigger = new ChangeTrigger(factory, publisher,seedProperties); } @Test From cc1ae5a5d42d7a47396964f6ef7bcc5a754603e1 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:10:57 +0200 Subject: [PATCH 086/310] add the variable seedProperties and modify the constructor Seed() and the method getDemoFiles() --- src/main/java/de/bonndan/nivio/input/Seed.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index cadc889b2..f992ee8f2 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.config.ConfigurableEnvVars; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,11 +27,14 @@ public class Seed { private final List seed; + private final SeedProperties seedProperties; + /** * @param seed comma separated urls * @throw RuntimeException to fail early on wrong config */ - public Seed(Optional seed) { + public Seed(Optional seed, SeedProperties seedProperties) { + this.seedProperties = seedProperties; if (seed.isEmpty()) { this.seed = new ArrayList<>(); return; @@ -62,10 +66,10 @@ private URL asURL(String s) { */ public List getDemoFiles() { List demoFiles = new ArrayList<>(); - if (ConfigurableEnvVars.DEMO.value().isEmpty()) { + if (seedProperties.getSeed().isEmpty()) { return demoFiles; } - String value = ConfigurableEnvVars.DEMO.value().get(); + String value = seedProperties.getSeed(); Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); From 27220d2bd5105bf4c8ac141d0d2d03a54e639bb4 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:14:21 +0200 Subject: [PATCH 087/310] modify the variable seed in the methods twoLocal(),http() and fails() --- src/test/java/de/bonndan/nivio/input/SeedTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/SeedTest.java b/src/test/java/de/bonndan/nivio/input/SeedTest.java index 2bbf17871..24982cbe3 100644 --- a/src/test/java/de/bonndan/nivio/input/SeedTest.java +++ b/src/test/java/de/bonndan/nivio/input/SeedTest.java @@ -17,7 +17,7 @@ public class SeedTest { public void twoLocal() throws MalformedURLException { Path currentRelativePath = Paths.get(""); String root = currentRelativePath.toAbsolutePath().toString(); - Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml," + root + "/src/test/resources/example/inout.yml")); + Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml," + root + "/src/test/resources/example/inout.yml"), null); List locations = seed.getLocations(); assertFalse(locations.isEmpty()); @@ -30,7 +30,7 @@ public void twoLocal() throws MalformedURLException { public void http() { Path currentRelativePath = Paths.get(""); String root = currentRelativePath.toAbsolutePath().toString(); - Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml,http://somehost.com/somefile.yml")); + Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml,http://somehost.com/somefile.yml"), null); List locations = seed.getLocations(); assertFalse(locations.isEmpty()); @@ -40,6 +40,6 @@ public void http() { @Test public void fails() { - assertThrows(RuntimeException.class, () -> new Seed(java.util.Optional.of(" :xxx"))); + assertThrows(RuntimeException.class, () -> new Seed(java.util.Optional.of(" :xxx"), null)); } } From 860b51e8b481a8c49879b6508f92ef7d8103ca01 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:18:02 +0200 Subject: [PATCH 088/310] modify the bean seed() --- src/main/java/de/bonndan/nivio/config/ApplicationConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index 06be8403f..1ef36c493 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -42,7 +42,7 @@ public RestTemplate restTemplate() { @Bean public Seed seed() { - return new Seed(Optional.ofNullable(seedProperties.getSeed())); + return new Seed(Optional.ofNullable(seedProperties.getSeed()),seedProperties); } @Bean From bc8912015f1499e2c5f0078781103554b98c028e Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Thu, 8 Jul 2021 11:39:07 +0200 Subject: [PATCH 089/310] add the variable seedProperties and modify the constructor and the method onApplicationEvent() --- src/main/java/de/bonndan/nivio/input/StartupListener.java | 7 +++++-- .../java/de/bonndan/nivio/input/StartupListenerTest.java | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/StartupListener.java b/src/main/java/de/bonndan/nivio/input/StartupListener.java index ca266a543..0c8a14075 100644 --- a/src/main/java/de/bonndan/nivio/input/StartupListener.java +++ b/src/main/java/de/bonndan/nivio/input/StartupListener.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.config.ConfigurableEnvVars; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,19 +28,21 @@ public class StartupListener implements ApplicationListener Date: Thu, 8 Jul 2021 11:46:04 +0200 Subject: [PATCH 090/310] modify the variable seed and the methods setup() and fires() --- .../java/de/bonndan/nivio/input/StartupListenerTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java index 581e4bdce..f1b96c6ad 100644 --- a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java +++ b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java @@ -23,14 +23,15 @@ class StartupListenerTest { private LandscapeDescriptionFactory factory; private ApplicationEventPublisher publisher; private StartupListener startupListener; - private SeedProperties seedProperties = null; + private SeedProperties seedProperties; private Seed seed = new Seed(Optional.empty(), null); // will use Seed.NIVIO_ENV_DIRECTORY + @BeforeEach public void setup() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - startupListener = new StartupListener(factory, publisher, seed); + startupListener = new StartupListener(factory, publisher, seed,seedProperties); } @Test @@ -38,7 +39,7 @@ public void fires() throws MalformedURLException { //given seed = new Seed(Optional.of("https://dedica.team"),null); - startupListener = new StartupListener(factory, publisher, seed); + startupListener = new StartupListener(factory, publisher, seed,seedProperties); LandscapeDescription landscapeDescription = new LandscapeDescription("foo", "bar", null); landscapeDescription.setSource(new LandscapeSource(new URL("https://dedica.team"))); From c3eeb6d017333a0d535dc13a59e6222cba8f58ea Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 8 Jul 2021 19:36:21 +0000 Subject: [PATCH 091/310] fix: upgrade org.kohsuke:github-api from 1.130 to 1.131 Snyk has created this PR to upgrade org.kohsuke:github-api from 1.130 to 1.131. See this package in Maven Repository: https://mvnrepository.com/artifact/org.kohsuke/github-api/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bc2dd90aa..318c4a52c 100644 --- a/pom.xml +++ b/pom.xml @@ -242,7 +242,7 @@ org.kohsuke github-api - 1.130 + 1.131 From 6b865c6b7db6a9f6761f58442aff4f224c63ba83 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Fri, 9 Jul 2021 06:49:21 +0200 Subject: [PATCH 092/310] [#564] framework key to freetext search --- docs/source/schema/Models/ItemDescription.rst | 10 ++-- docs/source/schema/Models/KPIConfig.rst | 2 +- .../schema/Models/LandscapeDescription.rst | 14 +++--- docs/source/schema/spec.json | 49 ++++++++++--------- .../java/de/bonndan/nivio/model/Label.java | 2 +- .../java/de/bonndan/nivio/model/Labeled.java | 3 ++ .../nivio/search/SearchDocumentFactory.java | 26 ++++++++-- .../de/bonndan/nivio/search/SearchIndex.java | 10 +++- .../search/SearchDocumentFactoryTest.java | 7 ++- 9 files changed, 78 insertions(+), 45 deletions(-) diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..15e810f36 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -88,16 +88,16 @@ List of configuration sources. Handled in the given order, latter extend/overwri - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - statuses - - List - - A list of statuses that works like hardcoded KPIs. - - optional, defaults to null - - null * - frameworks - Map - The parts used to create the item. Usually refers to technical frameworks. - optional, defaults to null - java: 8 + * - statuses + - List + - A list of statuses that works like hardcoded KPIs. + - optional, defaults to null + - null * - tags - List - diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index 8838e6fc9..e170f09ad 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -21,7 +21,7 @@ The configuration of landscape specific key performance indicators that derive s * - label - String - Key of the label to evaluate - - optional, defaults to null + - **required**, defaults to null - costs * - messageTemplate - String diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..00e78c967 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,12 +63,17 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - color + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null + * - icon - String - - optional, defaults to null - null - * - icon + * - color - String - - optional, defaults to null @@ -78,11 +83,6 @@ LandscapeDescription - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 60951921a..2afd4a10c 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -200,20 +200,13 @@ "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", "example" : "service|database|volume" }, - "status" : { - "type" : "array", - "description" : "A list of statuses that works like hardcoded KPIs.", + "lifecycle" : { + "type" : "string", + "description" : "The lifecycle state of an item.", "writeOnly" : true, - "items" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A list of statuses that works like hardcoded KPIs." - }, - "description" : "A list of statuses that works like hardcoded KPIs." - } + "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] }, - "statuses" : { + "status" : { "type" : "array", "description" : "A list of statuses that works like hardcoded KPIs.", "writeOnly" : true, @@ -237,11 +230,18 @@ "writeOnly" : true, "example" : "java: 8" }, - "lifecycle" : { - "type" : "string", - "description" : "The lifecycle state of an item.", + "statuses" : { + "type" : "array", + "description" : "A list of statuses that works like hardcoded KPIs.", "writeOnly" : true, - "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A list of statuses that works like hardcoded KPIs." + }, + "description" : "A list of statuses that works like hardcoded KPIs." + } }, "tags" : { "type" : "array", @@ -261,6 +261,7 @@ "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." }, "KPIConfig" : { + "required" : [ "label" ], "type" : "object", "properties" : { "description" : { @@ -407,14 +408,6 @@ }, "description" : "Additional labels for the landscape." }, - "items" : { - "type" : "array", - "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/ItemDescription" - } - }, "partial" : { "type" : "boolean", "description" : "marks that the landscape is not complete, but an update" @@ -425,6 +418,14 @@ "color" : { "type" : "string" }, + "items" : { + "type" : "array", + "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", + "writeOnly" : true, + "items" : { + "$ref" : "#/components/schemas/ItemDescription" + } + }, "links" : { "type" : "object", "additionalProperties" : { diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 189026bbe..b4f935afb 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -62,7 +62,7 @@ public enum Label { * Separator for label key parts. * Should not be used outside this package. Use key() methods instead. */ - static final String DELIMITER = "."; + public static final String DELIMITER = "."; public final String meaning; public final boolean isPrefix; diff --git a/src/main/java/de/bonndan/nivio/model/Labeled.java b/src/main/java/de/bonndan/nivio/model/Labeled.java index 5bbc6db9c..b9491001b 100644 --- a/src/main/java/de/bonndan/nivio/model/Labeled.java +++ b/src/main/java/de/bonndan/nivio/model/Labeled.java @@ -16,6 +16,9 @@ */ public interface Labeled { + /** + * Used to concatenate values when same-prefix labels are grouped. + */ String PREFIX_VALUE_DELIMITER = ";"; /** diff --git a/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java b/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java index 8360fd260..a59f61c92 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java +++ b/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java @@ -3,6 +3,8 @@ import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Labeled; +import joptsimple.internal.Strings; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; @@ -27,6 +29,11 @@ public class SearchDocumentFactory { public static final String LUCENE_FIELD_IDENTIFIER = "identifier"; public static final String LUCENE_FIELD_NAME = "name"; public static final String LUCENE_FIELD_DESCRIPTION = "description"; + + /** + * This is used to collect strings which should be directly searchable + */ + public static final String LUCENE_FIELD_GENERIC = "generic"; public static final String LUCENE_FIELD_CONTACT = "contact"; public static final String LUCENE_FIELD_FQI = "fqi"; public static final String LUCENE_FIELD_COMPONENT_TYPE = "component"; @@ -64,7 +71,7 @@ public static Document from(@NonNull final Item item, @Nullable List genericStrings = new ArrayList<>(); BiConsumer addTextField = (field, value) -> Optional.ofNullable(value) .ifPresentOrElse( val -> document.add(new TextField(field, val, Field.Store.YES)), @@ -83,9 +90,15 @@ public static Document from(@NonNull final Item item, @Nullable List { - if (StringUtils.isEmpty(val)) + if (StringUtils.isEmpty(val)) { return; + } addTextField.accept(labelKey, val); + + //add non-prefixed label values to generic field + if (!labelKey.contains(Label.DELIMITER)) { + genericStrings.add(val); + } }); //add links, title as key (duplicates are ok) @@ -98,7 +111,9 @@ public static Document from(@NonNull final Item item, @Nullable List addTextField.accept(LUCENE_FIELD_TAG, tag.toLowerCase(Locale.ROOT))); + Arrays.stream(item.getTags()) + .map(tag -> tag.toLowerCase(Locale.ROOT)) + .forEach(tag -> addTextField.accept(LUCENE_FIELD_TAG, tag)); //networks item.getLabels(Label.network).forEach((key, value) -> addTextField.accept(LUCENE_FIELD_NETWORK, value.toLowerCase(Locale.ROOT))); @@ -110,10 +125,10 @@ public static Document from(@NonNull final Item item, @Nullable List addTextField.accept(LUCENE_FIELD_FRAMEWORK, s)); - //kpis, fields are prefixed to prevent name collisions (kpis can have any names) statusValues.forEach(statusValue -> { final String field = statusValue.getField().startsWith(StatusValue.SUMMARY_LABEL) ? @@ -121,6 +136,9 @@ public static Document from(@NonNull final Item item, @Nullable List facets() { LOGGER.warn("Unable to get the facets for the given query error: ", e); } - return null; + return Collections.emptyList(); } private List documentSearch(String queryString) throws IOException, ParseException { @@ -169,7 +175,7 @@ private List documentSearch(String queryString) throws IOException, Pa DirectoryReader ireader = DirectoryReader.open(searchIndex); IndexSearcher isearcher = new IndexSearcher(ireader); // Parse a simple query that searches for "text": - QueryParser parser = new MultiFieldQueryParser(new String[]{LUCENE_FIELD_IDENTIFIER, LUCENE_FIELD_NAME, LUCENE_FIELD_DESCRIPTION}, new StandardAnalyzer()); + QueryParser parser = new MultiFieldQueryParser(MULTI_FIELD_QUERY_FIELDS, new StandardAnalyzer()); parser.setAllowLeadingWildcard(true); parser.setSplitOnWhitespace(true); parser.setDefaultOperator(QueryParser.Operator.AND); diff --git a/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java b/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java index 838d15ffc..8f76b42e9 100644 --- a/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java @@ -47,7 +47,7 @@ void setup() throws MalformedURLException { } @Test - public void generatesDocument() { + void generatesDocument() { //given @@ -85,6 +85,11 @@ public void generatesDocument() { assertThat(frameworks).contains("java"); String javaVersion = Arrays.stream(document.getValues("java")).findFirst().orElseThrow(); assertThat(javaVersion).isEqualTo("8"); + + String genericField = document.get(LUCENE_FIELD_GENERIC); + assertThat(genericField).contains("java").contains("spring").contains("boot"); + assertThat(genericField).contains("bar2"); //label + assertThat(genericField).doesNotContain("2.0.1"); //not framework version/value } @Test From b136f0bd5185650689998e8a520aaa2cc94ec479 Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 9 Jul 2021 14:42:05 +0200 Subject: [PATCH 093/310] Refactor Code --- docs/source/schema/Models/ItemDescription.rst | 4 +- docs/source/schema/spec.json | 182 +++++++++--------- .../input/kubernetes/DeploymentItem.java | 11 +- .../InputFormatHandlerKubernetes.java | 42 ++-- .../bonndan/nivio/input/kubernetes/Item.java | 41 ++-- .../input/kubernetes/LevelDecorator.java | 13 ++ .../kubernetes/PersistentVolumeClaimItem.java | 10 +- .../kubernetes/PersistentVolumeItem.java | 10 +- .../nivio/input/kubernetes/PodItem.java | 11 +- .../input/kubernetes/ReplicaSetItem.java | 11 +- .../nivio/input/kubernetes/ServiceItem.java | 10 +- .../input/kubernetes/StatefulSetItem.java | 10 +- .../input/kubernetes/DeploymentItemTest.java | 112 ++++++++++- .../input/kubernetes/KubernetesTest.java | 37 ---- .../PersistentVolumeClaimItemTest.java | 62 ++++-- .../kubernetes/PersistentVolumeItemTest.java | 112 +++++++++++ .../nivio/input/kubernetes/PodItemTest.java | 118 ++++++++++++ .../input/kubernetes/ReplicaSetItemTest.java | 133 +++++++++++++ .../input/kubernetes/ServiceItemTest.java | 112 +++++++++++ .../input/kubernetes/StatefulSetItemTest.java | 116 +++++++++++ 20 files changed, 948 insertions(+), 209 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 022f72838..18a1c4582 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -83,12 +83,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The lifecycle state of an item. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index a9900d882..ca3e44c5a 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -162,34 +162,34 @@ "group" : { "type" : "string", "description" : "The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common.", - "example" : "shipping" + "example": "shipping" }, - "interfaces" : { - "uniqueItems" : true, - "type" : "array", - "description" : "A collection of low level interfaces. Can be used to describe HTTP API endpoints for instance.", - "items" : { - "$ref" : "#/components/schemas/InterfaceDescription" + "interfaces": { + "uniqueItems": true, + "type": "array", + "description": "A collection of low level interfaces. Can be used to describe HTTP API endpoints for instance.", + "items": { + "$ref": "#/components/schemas/InterfaceDescription" } }, - "providedBy" : { - "type" : "array", - "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", - "example" : "shipping-mysqldb", - "items" : { - "type" : "string", - "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", - "example" : "shipping-mysqldb" + "providedBy": { + "type": "array", + "description": "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", + "example": "shipping-mysqldb", + "items": { + "type": "string", + "description": "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", + "example": "shipping-mysqldb" } }, - "icon" : { - "type" : "string", - "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." + "icon": { + "type": "string", + "description": "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." }, - "color" : { - "type" : "string", - "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", - "example" : "4400FF" + "color": { + "type": "string", + "description": "Overrides the group color. Use an HTML hex color code without the leading hash.", + "example": "4400FF" }, "address": { "type": "string", @@ -213,7 +213,7 @@ "EOL" ] }, - "statuses": { + "status": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -226,7 +226,7 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "status": { + "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -239,30 +239,30 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "frameworks" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "example" : "java: 8" + "frameworks": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "The parts used to create the item. Usually refers to technical frameworks.", + "example": "java: 8" }, - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "writeOnly" : true, - "example" : "java: 8" + "description": "The parts used to create the item. Usually refers to technical frameworks.", + "writeOnly": true, + "example": "java: 8" }, - "tags" : { - "type" : "array", - "items" : { - "type" : "string" + "tags": { + "type": "array", + "items": { + "type": "string" } }, - "links" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" + "links": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Link" }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example": "github: https://github.com/dedica-team/nivio" } }, "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." @@ -282,34 +282,34 @@ "description": "Key of the label to evaluate", "example": "costs" }, - "messageTemplate" : { - "type" : "string", - "description" : "Template for the displayed message, containing a placeholder for the assessed value '%s", - "example" : "The current value is: %s" + "messageTemplate": { + "type": "string", + "description": "Template for the displayed message, containing a placeholder for the assessed value '%s", + "example": "The current value is: %s" }, - "ranges" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", - "example" : "GREEN: 0;99.999999" + "ranges": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", + "example": "GREEN: 0;99.999999" }, - "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", - "example" : "GREEN: 0;99.999999" + "description": "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", + "example": "GREEN: 0;99.999999" }, - "matches" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", - "example" : "RED: BAD;err.*" + "matches": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", + "example": "RED: BAD;err.*" }, - "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", - "example" : "RED: BAD;err.*" + "description": "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", + "example": "RED: BAD;err.*" }, - "enabled" : { - "type" : "boolean", - "description" : "A flag indicating that the KPI is active. Can be used to disable default kpis." + "enabled": { + "type": "boolean", + "description": "A flag indicating that the KPI is active. Can be used to disable default kpis." } }, "description" : "The configuration of landscape specific key performance indicators that derive status information from landscape components. Usually the KPIs work on labels" @@ -382,30 +382,30 @@ "description" : "A brief description of the landscape." }, "owner" : { - "type" : "string", - "description" : "The business owner (person or team), preferably an email address." + "type": "string", + "description": "The business owner (person or team), preferably an email address." }, - "templates" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/ItemDescription" + "templates": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ItemDescription" }, - "description" : "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." + "description": "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." }, - "sources" : { - "type" : "array", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/SourceReference" + "sources": { + "type": "array", + "writeOnly": true, + "items": { + "$ref": "#/components/schemas/SourceReference" } }, - "config" : { - "$ref" : "#/components/schemas/LandscapeConfig" + "config": { + "$ref": "#/components/schemas/LandscapeConfig" }, - "groups" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/GroupDescription" + "groups": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/GroupDescription" }, "description": "Description of item groups (optional, can also be given in sources)." }, @@ -433,15 +433,15 @@ }, "partial": { "type": "boolean", - "description" : "marks that the landscape is not complete, but an update" + "description": "marks that the landscape is not complete, but an update" }, - "links" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" + "links": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Link" }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example": "github: https://github.com/dedica-team/nivio" } } }, diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java index 540880056..cd2e8e866 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.Locale; @@ -15,17 +16,19 @@ public class DeploymentItem extends Item { private final Deployment deployment; - public DeploymentItem(String name, String uid, String type, Deployment deployment) { - super(name, uid, type); + public DeploymentItem(String name, String uid, String type, Deployment deployment, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.deployment = deployment; } @Override + @NonNull public HasMetadata getWrappedItem() { return deployment; } @Override + @NonNull public Map getStatus() { return super.getStatus().entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, @@ -38,10 +41,10 @@ public Map getStatus() { })); } - public static List getDeploymentItems(KubernetesClient client) { + public static List getDeploymentItems(@NonNull KubernetesClient client) { var deploymentList = client.apps().deployments().list().getItems(); return deploymentList.stream().map(deployment -> { - var deploymentItem = new DeploymentItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, deployment); + var deploymentItem = new DeploymentItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, deployment, new LevelDecorator(4)); deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); return deploymentItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 3dd254553..2ae29739b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -59,14 +59,25 @@ public List getFormats() { @Override public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { - this.client = getClient(reference.getUrl()); var persistentVolumeClaims = getPersistentVolumeClaimItems(client); var persistentVolumes = getPersistentVolumeItems(client); crossReferenceClaimer(persistentVolumeClaims, persistentVolumes); - var itemList = getK8sComponents(client); + var serviceItems = getServiceItems(client); + var deploymentItems = getDeploymentItems(client); + var statefulSetItems = getStatefulSetItems(client); + + crossReferenceService(serviceItems, deploymentItems); + crossReferenceService(serviceItems, statefulSetItems); + + var itemList = new ArrayList(); + itemList.addAll(getReplicaSetItems(client)); + itemList.addAll(getPodItems(client)); + itemList.addAll(serviceItems); + itemList.addAll(deploymentItems); + itemList.addAll(statefulSetItems); crossReferenceOwner(itemList); itemList.addAll(persistentVolumeClaims); @@ -75,16 +86,6 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti landscapeDescription.mergeItems(createItemDescription(itemList)); } - private ArrayList getK8sComponents(KubernetesClient client) { - var itemList = new ArrayList(); - itemList.addAll(getDeploymentItems(client)); - itemList.addAll(getReplicaSetItems(client)); - itemList.addAll(getPodItems(client)); - itemList.addAll(getServiceItems(client)); - itemList.addAll(getStatefulSetItems(client)); - return itemList; - } - private List createItemDescription(List itemList) { return itemList.stream().map(item -> { var itemDescription = new ItemDescription(); @@ -107,14 +108,21 @@ private void crossReferenceOwner(ArrayList items) { items.forEach(item -> { var owners = new ArrayList(); owners = (ArrayList) items.stream().filter(item1 -> item.getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(item1.getUid())).collect(Collectors.toList()); - item.setOwners(owners); + owners.forEach(item::addOwner); }); } - private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { + private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { persistentVolumes.forEach(item -> { var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) item.getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); - item.setOwners(new ArrayList<>(claimer)); + claimer.forEach(item::addOwner); + }); + } + + private void crossReferenceService(List service, List owners) { + service.forEach(item -> { + var claimer = owners.stream().filter(claimItem -> (item.getName().equals(claimItem.getName()))).collect(Collectors.toList()); + claimer.forEach(item::addOwner); }); } @@ -133,8 +141,4 @@ private KubernetesClient getClient(String context) { this.client = new DefaultKubernetesClient(config); return this.client; } - - public Config getConfiguration() { - return getClient("").getConfiguration(); - } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java index 2f0aec59a..3afae9e67 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -2,40 +2,40 @@ import de.bonndan.nivio.input.dto.RelationDescription; import io.fabric8.kubernetes.api.model.HasMetadata; +import org.springframework.lang.NonNull; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public abstract class Item { private final String name; - private List owners = new ArrayList<>(); - private final List relationDescriptionList = new ArrayList<>(); private final Map status = new HashMap<>(); private final String type; private final String uid; - protected Item(String name, String uid, String type) { + private final LevelDecorator levelDecorator; + + protected Item(String name, String uid, String type, LevelDecorator levelDecorator) { + this.levelDecorator = levelDecorator; this.name = name; this.uid = uid; this.type = type; } - public void addOwner(Item owner) { - this.owners.add(owner); + public void addOwner(@NonNull Item owner) { + this.owners.add(Objects.requireNonNull(owner)); } - public void addRelation(RelationDescription relationDescription) { - relationDescriptionList.add(relationDescription); + public void addRelation(@NonNull RelationDescription relationDescription) { + relationDescriptionList.add(Objects.requireNonNull(relationDescription)); } - public void addStatus(String key, String value) { - status.put(key, value); + public void addStatus(@NonNull String key, @NonNull String value) { + status.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); } + @NonNull public String getGroup() { if (this.getOwner().isEmpty()) { return name; @@ -44,33 +44,44 @@ public String getGroup() { } } + public LevelDecorator getLevelDecorator() { + return levelDecorator; + } + + @NonNull public String getName() { return name; } + @NonNull public List getOwner() { return owners; } + @NonNull public List getRelationDescriptionList() { return relationDescriptionList; } + @NonNull public Map getStatus() { return status; } + @NonNull public String getType() { return type; } + @NonNull public String getUid() { return uid; } + @NonNull public abstract HasMetadata getWrappedItem(); - public void setOwners(List owners) { - this.owners = owners; + public void setOwners(@NonNull List owners) { + this.owners = Objects.requireNonNull(owners); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java b/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java new file mode 100644 index 000000000..32984f9e9 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java @@ -0,0 +1,13 @@ +package de.bonndan.nivio.input.kubernetes; + +public class LevelDecorator { + int level; + + public LevelDecorator(int level) { + this.level = level; + } + + public int getLevel() { + return level; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java index e9f67c0c2..0434f27f7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java @@ -4,6 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.stream.Collectors; @@ -11,18 +12,19 @@ public class PersistentVolumeClaimItem extends Item { private final PersistentVolumeClaim persistentVolumeClaim; - protected PersistentVolumeClaimItem(String name, String uid, String type, PersistentVolumeClaim persistentVolumeClaim) { - super(name, uid, type); + protected PersistentVolumeClaimItem(String name, String uid, String type, PersistentVolumeClaim persistentVolumeClaim, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.persistentVolumeClaim = persistentVolumeClaim; } @Override + @NonNull public HasMetadata getWrappedItem() { return persistentVolumeClaim; } - public static List getPersistentVolumeClaimItems(KubernetesClient client) { + public static List getPersistentVolumeClaimItems(KubernetesClient client) { var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new PersistentVolumeClaimItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims)).collect(Collectors.toList()); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new PersistentVolumeClaimItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims, new LevelDecorator(1))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java index 0d5deb821..0c2777a2b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java @@ -4,6 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.PersistentVolume; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.stream.Collectors; @@ -11,18 +12,19 @@ public class PersistentVolumeItem extends Item { private final PersistentVolume persistentVolume; - protected PersistentVolumeItem(String name, String uid, String type, PersistentVolume persistentVolume) { - super(name, uid, type); + protected PersistentVolumeItem(String name, String uid, String type, PersistentVolume persistentVolume, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.persistentVolume = persistentVolume; } @Override + @NonNull public HasMetadata getWrappedItem() { return persistentVolume; } - public static List getPersistentVolumeItems(KubernetesClient client) { + public static List getPersistentVolumeItems(KubernetesClient client) { var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolumeClaims -> new PersistentVolumeItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims)).collect(Collectors.toList()); + return getPersistentVolumeList.stream().map(persistentVolumeClaims -> new PersistentVolumeItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims, new LevelDecorator(0))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java index a8b485d16..0fd9f35e7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -5,6 +5,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.Locale; @@ -14,17 +15,19 @@ public class PodItem extends Item { private final Pod pod; - protected PodItem(String name, String uid, String type, Pod pod) { - super(name, uid, type); + protected PodItem(String name, String uid, String type, Pod pod, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.pod = pod; } @Override + @NonNull public HasMetadata getWrappedItem() { return pod; } @Override + @NonNull public Map getStatus() { return super.getStatus().entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, @@ -37,10 +40,10 @@ public Map getStatus() { })); } - public static List getPodItems(KubernetesClient client) { + public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new PodItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, pod); + var podItem = new PodItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, pod, new LevelDecorator(2)); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java index 602078966..26712fe1b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -7,6 +7,7 @@ import io.fabric8.kubernetes.api.model.apps.ReplicaSet; import io.fabric8.kubernetes.client.KubernetesClient; import org.apache.commons.collections.map.SingletonMap; +import org.springframework.lang.NonNull; import java.util.List; import java.util.Map; @@ -16,17 +17,19 @@ public class ReplicaSetItem extends Item { private final ReplicaSet replicaSet; - protected ReplicaSetItem(String name, String uid, String type, ReplicaSet replicaSet) { - super(name, uid, type); + protected ReplicaSetItem(String name, String uid, String type, ReplicaSet replicaSet, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.replicaSet = replicaSet; } @Override + @NonNull public HasMetadata getWrappedItem() { return replicaSet; } @Override + @NonNull public Map getStatus() { var replicaCount = replicaSet.getSpec().getReplicas(); var replicaCountDesired = Integer.valueOf(replicaSet.getMetadata().getAnnotations().get("deployment.kubernetes.io/desired-replicas")); @@ -39,10 +42,10 @@ public Map getStatus() { return new SingletonMap(message, Status.ORANGE.toString()); } - public static List getReplicaSetItems(KubernetesClient client) { + public static List getReplicaSetItems(KubernetesClient client) { var replicaSetList = client.apps().replicaSets().list().getItems(); return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new ReplicaSetItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, replicaSet); + var replicaSetItem = new ReplicaSetItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, replicaSet, new LevelDecorator(3)); replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); return replicaSetItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java index 6d2cc2265..a4ce12248 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -4,6 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.stream.Collectors; @@ -11,18 +12,19 @@ public class ServiceItem extends Item { private final Service service; - protected ServiceItem(String name, String uid, String type, Service service) { - super(name, uid, type); + protected ServiceItem(String name, String uid, String type, Service service, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.service = service; } @Override + @NonNull public HasMetadata getWrappedItem() { return service; } - public static List getServiceItems(KubernetesClient client) { + public static List getServiceItems(KubernetesClient client) { var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new ServiceItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, service)).collect(Collectors.toList()); + return serviceList.stream().map(service -> new ServiceItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, service, new LevelDecorator(-1))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java index ae25cea7c..0bbd68f90 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -4,6 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.StatefulSet; import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; import java.util.List; import java.util.stream.Collectors; @@ -11,18 +12,19 @@ public class StatefulSetItem extends Item { private final StatefulSet statefulSet; - protected StatefulSetItem(String name, String uid, String type, StatefulSet statefulSet) { - super(name, uid, type); + protected StatefulSetItem(String name, String uid, String type, StatefulSet statefulSet, LevelDecorator levelDecorator) { + super(name, uid, type, levelDecorator); this.statefulSet = statefulSet; } @Override + @NonNull public HasMetadata getWrappedItem() { return statefulSet; } - public static List getStatefulSetItems(KubernetesClient client) { + public static List getStatefulSetItems(KubernetesClient client) { var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new StatefulSetItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, statefulSet)).collect(Collectors.toList()); + return statefulSetList.stream().map(statefulSet -> new StatefulSetItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, statefulSet, new LevelDecorator(3))).collect(Collectors.toList()); } } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java index de83994a3..ae8c728c1 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java @@ -1,18 +1,122 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder; +import io.fabric8.kubernetes.api.model.apps.DeploymentStatusBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) class DeploymentItemTest { + Deployment deployment; + DeploymentItem deploymentItem; + KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + deployment = new DeploymentBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new DeploymentSpecBuilder() + .build()) + .withStatus(new DeploymentStatusBuilder() + .build()) + .build(); + kubernetesClient.apps().deployments().create(deployment); + + deploymentItem = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, deployment, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = deploymentItem.getWrappedItem(); + assertThat(result).isEqualTo(deployment); + } + + @Test + void testGetDeploymentItems() { + List result = DeploymentItem.getDeploymentItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, deployment, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(deploymentItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); + deploymentItem.addOwner(owner); + assertThat(deploymentItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> deploymentItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + deploymentItem.addRelation(relation); + assertThat(deploymentItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> deploymentItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatusGreen() { + deploymentItem.addStatus("key", "true"); + assertThat(deploymentItem.getStatus()).isEqualTo(Collections.singletonMap("key", "green")); + } + + @Test + void testAddStatusRed() { + deploymentItem.addStatus("key", "false"); + assertThat(deploymentItem.getStatus()).isEqualTo(Collections.singletonMap("key", "red")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> deploymentItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> deploymentItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> deploymentItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } @Test - void getWrappedItem() { + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); + deploymentItem.addOwner(owner); + String result = deploymentItem.getGroup(); + assertThat(result).isEqualTo("test"); } @Test - void getStatus() { + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4))); + deploymentItem.setOwners(owner); + assertThat(deploymentItem.getOwner()).isEqualTo(owner); } @Test - void getDeploymentItems() { + void testSetOwnersNull() { + assertThatThrownBy(() -> deploymentItem.setOwners(null)).isInstanceOf(NullPointerException.class); } -} \ No newline at end of file +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java index 5b1b4ddb8..21e75ebe1 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java @@ -1,9 +1,5 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.ItemDescription; -import de.bonndan.nivio.input.dto.LandscapeDescription; -import de.bonndan.nivio.input.dto.SourceReference; import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.PodSpecBuilder; @@ -11,15 +7,11 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; import java.util.Map; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - @EnableKubernetesMockClient(crud = true) public class KubernetesTest { @@ -50,33 +42,4 @@ void setup() { client.pods().inNamespace("default").create(pod); } - - @Test - public void testRead() { - - SourceReference sourceReference = new SourceReference(null, "k8s"); - sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); - - InputFormatHandlerKubernetes factory = new InputFormatHandlerKubernetes(java.util.Optional.ofNullable(client)); - factory.getConfiguration().setNamespace("default"); - - LandscapeDescription landscapeDescription = new LandscapeDescription("test"); - - //when - factory.applyData(sourceReference, null, landscapeDescription); - - //then - assertEquals(3, landscapeDescription.getItemDescriptions().all().size()); - - ItemDescription itemDescription = landscapeDescription.getItemDescriptions().all().stream() - .filter(itemDescription1 -> ItemType.POD.equals(itemDescription1.getType())) - .findFirst() - .get(); - assertNotNull(itemDescription); - - assertEquals("testgroup", itemDescription.getGroup()); - assertEquals("pod1", itemDescription.getName()); - assertEquals("pod1", itemDescription.getIdentifier()); - assertEquals("testgroup", itemDescription.getLabels().get("release")); - } } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java index ba652d754..799970cb5 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java @@ -5,8 +5,6 @@ import io.fabric8.kubernetes.api.model.*; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -15,12 +13,12 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; @EnableKubernetesMockClient(crud = true, https = false) class PersistentVolumeClaimItemTest { PersistentVolumeClaim persistentVolumeClaim; PersistentVolumeClaimItem persistentVolumeClaimItem; - KubernetesMockServer kubernetesMockServer = new KubernetesMockServer(); static KubernetesClient kubernetesClient; @BeforeEach @@ -28,7 +26,8 @@ void setUp() { persistentVolumeClaim = new PersistentVolumeClaimBuilder() .withNewMetadata() .withName("test") - .withNamespace("default") + .withNamespace("test") + .withUid("1234") .withLabels(Map.of("release", "testgroup")) .endMetadata() .withSpec(new PersistentVolumeClaimSpecBuilder() @@ -37,8 +36,9 @@ void setUp() { .withStatus(new PersistentVolumeClaimStatusBuilder() .build()) .build(); - persistentVolumeClaimItem = new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim); - kubernetesClient.persistentVolumeClaims().inNamespace("default").create(persistentVolumeClaim); + kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); + + persistentVolumeClaimItem = new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim, new LevelDecorator(4)); } @Test @@ -49,30 +49,66 @@ void testGetWrappedItem() { @Test void testGetPersistentVolumeClaimItems() { - - var test = kubernetesClient.persistentVolumeClaims().list().getItems(); - List result = PersistentVolumeClaimItem.getPersistentVolumeClaimItems(kubernetesClient); - assertThat(Collections.singletonList(new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim))).isEqualTo(result); + List result = PersistentVolumeClaimItem.getPersistentVolumeClaimItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(persistentVolumeClaimItem)); } @Test void testAddOwner() { - persistentVolumeClaimItem.addOwner(null); + var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); + persistentVolumeClaimItem.addOwner(owner); + assertThat(persistentVolumeClaimItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> persistentVolumeClaimItem.addOwner(null)).isInstanceOf(NullPointerException.class); } @Test void testAddRelation() { - persistentVolumeClaimItem.addRelation(new RelationDescription("source", "target")); + var relation = new RelationDescription("source", "target"); + persistentVolumeClaimItem.addRelation(relation); + assertThat(persistentVolumeClaimItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> persistentVolumeClaimItem.addRelation(null)).isInstanceOf(NullPointerException.class); } @Test void testAddStatus() { persistentVolumeClaimItem.addStatus("key", "value"); + assertThat(persistentVolumeClaimItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); } @Test void testGetGroup() { + + var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); + persistentVolumeClaimItem.addOwner(owner); String result = persistentVolumeClaimItem.getGroup(); - Assertions.assertEquals("replaceMeWithExpectedResult", result); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4))); + persistentVolumeClaimItem.setOwners(owner); + assertThat(persistentVolumeClaimItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> persistentVolumeClaimItem.setOwners(null)).isInstanceOf(NullPointerException.class); } } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java new file mode 100644 index 000000000..3158c5983 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java @@ -0,0 +1,112 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) +class PersistentVolumeItemTest { + PersistentVolume persistentVolume; + PersistentVolumeItem persistentVolumeItem; + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + persistentVolume = new PersistentVolumeBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new PersistentVolumeSpecBuilder() + .build()) + .withStatus(new PersistentVolumeStatusBuilder() + .build()) + .build(); + kubernetesClient.persistentVolumes().create(persistentVolume); + + persistentVolumeItem = new PersistentVolumeItem("test", "1234", ItemType.VOLUME, persistentVolume, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = persistentVolumeItem.getWrappedItem(); + assertThat(result).isEqualTo(persistentVolume); + } + + @Test + void testGetPersistentVolumeItems() { + List result = PersistentVolumeItem.getPersistentVolumeItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new PersistentVolumeItem("test", "1234", ItemType.VOLUME, persistentVolume, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(persistentVolumeItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); + persistentVolumeItem.addOwner(owner); + assertThat(persistentVolumeItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> persistentVolumeItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + persistentVolumeItem.addRelation(relation); + assertThat(persistentVolumeItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> persistentVolumeItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatus() { + persistentVolumeItem.addStatus("key", "value"); + assertThat(persistentVolumeItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> persistentVolumeItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> persistentVolumeItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> persistentVolumeItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } + + @Test + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); + persistentVolumeItem.addOwner(owner); + String result = persistentVolumeItem.getGroup(); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4))); + persistentVolumeItem.setOwners(owner); + assertThat(persistentVolumeItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> persistentVolumeItem.setOwners(null)).isInstanceOf(NullPointerException.class); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java new file mode 100644 index 000000000..b2e4922ba --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java @@ -0,0 +1,118 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) +class PodItemTest { + Pod pod; + PodItem podItem; + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + pod = new PodBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new PodSpecBuilder() + .build()) + .withStatus(new PodStatusBuilder() + .build()) + .build(); + kubernetesClient.pods().create(pod); + + podItem = new PodItem("test", "1234", ItemType.POD, pod, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = podItem.getWrappedItem(); + assertThat(result).isEqualTo(pod); + } + + @Test + void testGetPodItems() { + List result = PodItem.getPodItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new PodItem("test", "1234", ItemType.POD, pod, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(podItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4)); + podItem.addOwner(owner); + assertThat(podItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> podItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + podItem.addRelation(relation); + assertThat(podItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> podItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatusGreen() { + podItem.addStatus("key", "true"); + assertThat(podItem.getStatus()).isEqualTo(Collections.singletonMap("key", "green")); + } + + @Test + void testAddStatusRed() { + podItem.addStatus("key", "false"); + assertThat(podItem.getStatus()).isEqualTo(Collections.singletonMap("key", "red")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> podItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> podItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> podItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } + + @Test + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4)); + podItem.addOwner(owner); + String result = podItem.getGroup(); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4))); + podItem.setOwners(owner); + assertThat(podItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> podItem.setOwners(null)).isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java new file mode 100644 index 000000000..4f2135d91 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java @@ -0,0 +1,133 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.ReplicaSet; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetSpecBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetStatusBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) +class ReplicaSetItemTest { + ReplicaSet replicaSet; + ReplicaSetItem replicaSetItem; + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + replicaSet = new ReplicaSetBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .withAnnotations(new HashMap<>()) + .endMetadata() + .withSpec(new ReplicaSetSpecBuilder() + .build()) + .withStatus(new ReplicaSetStatusBuilder() + .build()) + .build(); + kubernetesClient.apps().replicaSets().create(replicaSet); + + replicaSetItem = new ReplicaSetItem("test", "1234", ItemType.REPLICASET, replicaSet, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = replicaSetItem.getWrappedItem(); + assertThat(result).isEqualTo(replicaSet); + } + + @Test + void testGetReplicaSetItems() { + List result = ReplicaSetItem.getReplicaSetItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new ReplicaSetItem("test", "1234", ItemType.REPLICASET, replicaSet, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(replicaSetItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.REPLICASET, null, new LevelDecorator(4)); + replicaSetItem.addOwner(owner); + assertThat(replicaSetItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> replicaSetItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + replicaSetItem.addRelation(relation); + assertThat(replicaSetItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> replicaSetItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatusGreen() { + ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(4); + replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); + assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("4 of 4 Pods are ready", "green")); + } + + @Test + void testAddStatusOrange() { + ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(2); + replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); + assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("2 of 4 Pods are ready", "orange")); + } + + @Test + void testAddStatusRed() { + ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(0); + replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); + assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("0 of 4 Pods are ready", "red")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> replicaSetItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> replicaSetItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> replicaSetItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } + + @Test + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); + replicaSetItem.addOwner(owner); + String result = replicaSetItem.getGroup(); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.REPLICASET, null, new LevelDecorator(4))); + replicaSetItem.setOwners(owner); + assertThat(replicaSetItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> replicaSetItem.setOwners(null)).isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java new file mode 100644 index 000000000..41a5f98ce --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java @@ -0,0 +1,112 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) +class ServiceItemTest { + Service service; + ServiceItem serviceItem; + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + service = new ServiceBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new ServiceSpecBuilder() + .build()) + .withStatus(new ServiceStatusBuilder() + .build()) + .build(); + kubernetesClient.services().create(service); + + serviceItem = new ServiceItem("test", "1234", ItemType.SERVICE, service, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = serviceItem.getWrappedItem(); + assertThat(result).isEqualTo(service); + } + + @Test + void testGetServiceItems() { + List result = ServiceItem.getServiceItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new ServiceItem("test", "1234", ItemType.SERVICE, service, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(serviceItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.SERVICE, null, new LevelDecorator(4)); + serviceItem.addOwner(owner); + assertThat(serviceItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> serviceItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + serviceItem.addRelation(relation); + assertThat(serviceItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> serviceItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatusStatus() { + serviceItem.addStatus("key", "value"); + assertThat(serviceItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> serviceItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> serviceItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> serviceItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } + + @Test + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); + serviceItem.addOwner(owner); + String result = serviceItem.getGroup(); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.SERVICE, null, new LevelDecorator(4))); + serviceItem.setOwners(owner); + assertThat(serviceItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> serviceItem.setOwners(null)).isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java new file mode 100644 index 000000000..8d85a0c0b --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java @@ -0,0 +1,116 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetSpecBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetStatusBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@EnableKubernetesMockClient(crud = true, https = false) +class StatefulSetItemTest { + StatefulSet stateful; + StatefulSetItem statefulItem; + static KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + stateful = new StatefulSetBuilder() + .withNewMetadata() + .withName("test") + .withNamespace("test") + .withUid("1234") + .withLabels(Map.of("release", "testgroup")) + .endMetadata() + .withSpec(new StatefulSetSpecBuilder() + .build()) + .withStatus(new StatefulSetStatusBuilder() + .build()) + .build(); + kubernetesClient.apps().statefulSets().create(stateful); + + statefulItem = new StatefulSetItem("test", "1234", ItemType.STATEFULSET, stateful, new LevelDecorator(4)); + } + + @Test + void testGetWrappedItem() { + HasMetadata result = statefulItem.getWrappedItem(); + assertThat(result).isEqualTo(stateful); + } + + @Test + void testGetStatefulSetItems() { + List result = StatefulSetItem.getStatefulSetItems(kubernetesClient); + assertThat(result.size()).isEqualTo(Collections.singletonList(new StatefulSetItem("test", "1234", ItemType.STATEFULSET, stateful, new LevelDecorator(4))).size()); + result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(statefulItem)); + } + + @Test + void testAddOwner() { + var owner = new DeploymentItem("test", "1234", ItemType.STATEFULSET, null, new LevelDecorator(4)); + statefulItem.addOwner(owner); + assertThat(statefulItem.getOwner()).isEqualTo(Collections.singletonList(owner)); + } + + @Test + void testAddOwnerNull() { + assertThatThrownBy(() -> statefulItem.addOwner(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddRelation() { + var relation = new RelationDescription("source", "target"); + statefulItem.addRelation(relation); + assertThat(statefulItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); + } + + @Test + void testAddRelationNull() { + assertThatThrownBy(() -> statefulItem.addRelation(null)).isInstanceOf(NullPointerException.class); + } + + @Test + void testAddStatus() { + statefulItem.addStatus("key", "value"); + assertThat(statefulItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); + } + + @Test + void testAddStatusNull() { + assertThatThrownBy(() -> statefulItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> statefulItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> statefulItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); + } + + @Test + void testGetGroup() { + var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); + statefulItem.addOwner(owner); + String result = statefulItem.getGroup(); + assertThat(result).isEqualTo("test"); + } + + @Test + void testSetOwners() { + List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.STATEFULSET, null, new LevelDecorator(4))); + statefulItem.setOwners(owner); + assertThat(statefulItem.getOwner()).isEqualTo(owner); + } + + @Test + void testSetOwnersNull() { + assertThatThrownBy(() -> statefulItem.setOwners(null)).isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file From 3033510287d9140950e2555ca0fcdbe29f99f27a Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 12 Jul 2021 10:54:12 +0200 Subject: [PATCH 094/310] Remove inheritance --- .../input/kubernetes/DeploymentItem.java | 15 +- .../InputFormatHandlerKubernetes.java | 16 +-- .../bonndan/nivio/input/kubernetes/Item.java | 84 +---------- .../nivio/input/kubernetes/K8sItem.java | 88 ++++++++++++ .../kubernetes/PersistentVolumeClaimItem.java | 16 ++- .../kubernetes/PersistentVolumeItem.java | 17 ++- .../nivio/input/kubernetes/PodItem.java | 16 +-- .../input/kubernetes/ReplicaSetItem.java | 13 +- .../nivio/input/kubernetes/ServiceItem.java | 16 ++- .../input/kubernetes/StatefulSetItem.java | 15 +- .../input/kubernetes/DeploymentItemTest.java | 21 +-- .../PersistentVolumeClaimItemTest.java | 114 --------------- .../kubernetes/PersistentVolumeItemTest.java | 112 --------------- .../nivio/input/kubernetes/PodItemTest.java | 118 ---------------- .../input/kubernetes/ReplicaSetItemTest.java | 133 ------------------ .../input/kubernetes/ServiceItemTest.java | 112 --------------- .../input/kubernetes/StatefulSetItemTest.java | 116 --------------- 17 files changed, 161 insertions(+), 861 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java index cd2e8e866..2a44150a6 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -13,24 +13,21 @@ import java.util.Map; import java.util.stream.Collectors; -public class DeploymentItem extends Item { +public class DeploymentItem implements Item { private final Deployment deployment; - public DeploymentItem(String name, String uid, String type, Deployment deployment, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public DeploymentItem(Deployment deployment) { this.deployment = deployment; } - @Override @NonNull public HasMetadata getWrappedItem() { return deployment; } - @Override @NonNull - public Map getStatus() { - return super.getStatus().entrySet().stream().collect(Collectors.toMap( + public Map getStatus(Map status) { + return status.entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, pair -> { if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { @@ -41,10 +38,10 @@ public Map getStatus() { })); } - public static List getDeploymentItems(@NonNull KubernetesClient client) { + public static List getDeploymentItems(@NonNull KubernetesClient client) { var deploymentList = client.apps().deployments().list().getItems(); return deploymentList.stream().map(deployment -> { - var deploymentItem = new DeploymentItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, deployment, new LevelDecorator(4)); + var deploymentItem = new K8sItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new DeploymentItem(deployment)); deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); return deploymentItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 2ae29739b..cc17733de 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -72,7 +72,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti crossReferenceService(serviceItems, deploymentItems); crossReferenceService(serviceItems, statefulSetItems); - var itemList = new ArrayList(); + var itemList = new ArrayList(); itemList.addAll(getReplicaSetItems(client)); itemList.addAll(getPodItems(client)); itemList.addAll(serviceItems); @@ -86,7 +86,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti landscapeDescription.mergeItems(createItemDescription(itemList)); } - private List createItemDescription(List itemList) { + private List createItemDescription(List itemList) { return itemList.stream().map(item -> { var itemDescription = new ItemDescription(); itemDescription.setIdentifier(item.getUid()); @@ -104,22 +104,22 @@ private List createItemDescription(List itemList) { }).collect(Collectors.toList()); } - private void crossReferenceOwner(ArrayList items) { + private void crossReferenceOwner(ArrayList items) { items.forEach(item -> { - var owners = new ArrayList(); - owners = (ArrayList) items.stream().filter(item1 -> item.getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(item1.getUid())).collect(Collectors.toList()); + var owners = new ArrayList(); + owners = (ArrayList) items.stream().filter(item1 -> item.getItemContainer().getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(item1.getUid())).collect(Collectors.toList()); owners.forEach(item::addOwner); }); } - private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { + private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { persistentVolumes.forEach(item -> { - var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) item.getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); + var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) item.getItemContainer().getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); claimer.forEach(item::addOwner); }); } - private void crossReferenceService(List service, List owners) { + private void crossReferenceService(List service, List owners) { service.forEach(item -> { var claimer = owners.stream().filter(claimItem -> (item.getName().equals(claimItem.getName()))).collect(Collectors.toList()); claimer.forEach(item::addOwner); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java index 3afae9e67..39b78215c 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -1,87 +1,11 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.dto.RelationDescription; import io.fabric8.kubernetes.api.model.HasMetadata; -import org.springframework.lang.NonNull; -import java.util.*; +import java.util.Map; -public abstract class Item { - private final String name; - private List owners = new ArrayList<>(); - private final List relationDescriptionList = new ArrayList<>(); - private final Map status = new HashMap<>(); - private final String type; - private final String uid; +public interface Item { + HasMetadata getWrappedItem(); - private final LevelDecorator levelDecorator; - - protected Item(String name, String uid, String type, LevelDecorator levelDecorator) { - this.levelDecorator = levelDecorator; - this.name = name; - this.uid = uid; - this.type = type; - } - - public void addOwner(@NonNull Item owner) { - this.owners.add(Objects.requireNonNull(owner)); - } - - public void addRelation(@NonNull RelationDescription relationDescription) { - relationDescriptionList.add(Objects.requireNonNull(relationDescription)); - } - - public void addStatus(@NonNull String key, @NonNull String value) { - status.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); - } - - @NonNull - public String getGroup() { - if (this.getOwner().isEmpty()) { - return name; - } else { - return this.getOwner().get(0).getGroup(); - } - } - - public LevelDecorator getLevelDecorator() { - return levelDecorator; - } - - @NonNull - public String getName() { - return name; - } - - @NonNull - public List getOwner() { - return owners; - } - - @NonNull - public List getRelationDescriptionList() { - return relationDescriptionList; - } - - @NonNull - public Map getStatus() { - return status; - } - - @NonNull - public String getType() { - return type; - } - - @NonNull - public String getUid() { - return uid; - } - - @NonNull - public abstract HasMetadata getWrappedItem(); - - public void setOwners(@NonNull List owners) { - this.owners = Objects.requireNonNull(owners); - } + Map getStatus(Map status); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java new file mode 100644 index 000000000..1b4513ede --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -0,0 +1,88 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.dto.RelationDescription; +import org.springframework.lang.NonNull; + +import java.util.*; + +public class K8sItem { + private final List relationDescriptionList = new ArrayList<>(); + private final Map status = new HashMap<>(); + private final List owners = new ArrayList<>(); + + private final LevelDecorator levelDecorator; + private final Item itemContainer; + private final String name; + private final String type; + private final String uid; + + public K8sItem(String name, String uid, String type, LevelDecorator levelDecorator, Item itemContainer) { + this.levelDecorator = levelDecorator; + this.itemContainer = itemContainer; + this.name = name; + this.type = type; + this.uid = uid; + } + + public void addOwner(@NonNull K8sItem owner) { + this.owners.add(Objects.requireNonNull(owner)); + } + + public void addRelation(@NonNull RelationDescription relationDescription) { + relationDescriptionList.add(Objects.requireNonNull(relationDescription)); + } + + public void addStatus(@NonNull String key, @NonNull String value) { + status.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); + } + + @NonNull + public String getGroup() { + if (this.getOwner().isEmpty()) { + return name; + } else { + return this.getOwner().get(0).getGroup(); + } + } + + public LevelDecorator getLevelDecorator() { + return levelDecorator; + } + + @NonNull + public String getName() { + return name; + } + + @NonNull + public List getOwner() { + return owners; + } + + @NonNull + public List getRelationDescriptionList() { + return relationDescriptionList; + } + + @NonNull + public Map getStatus() { + return Objects.requireNonNullElse(itemContainer.getStatus(this.status), this.status); + } + + @NonNull + public String getType() { + return type; + } + + @NonNull + public String getUid() { + return uid; + } + + @NonNull + public Item getItemContainer() { + return itemContainer; + } + +} + diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java index 0434f27f7..a23ce4143 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java @@ -7,24 +7,28 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -public class PersistentVolumeClaimItem extends Item { +public class PersistentVolumeClaimItem implements Item { private final PersistentVolumeClaim persistentVolumeClaim; - protected PersistentVolumeClaimItem(String name, String uid, String type, PersistentVolumeClaim persistentVolumeClaim, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public PersistentVolumeClaimItem(PersistentVolumeClaim persistentVolumeClaim) { this.persistentVolumeClaim = persistentVolumeClaim; } - @Override @NonNull public HasMetadata getWrappedItem() { return persistentVolumeClaim; } - public static List getPersistentVolumeClaimItems(KubernetesClient client) { + @Override + public Map getStatus(Map status) { + return null; + } + + public static List getPersistentVolumeClaimItems(KubernetesClient client) { var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new PersistentVolumeClaimItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims, new LevelDecorator(1))).collect(Collectors.toList()); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(1), new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java index 0c2777a2b..9c50a45cd 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java @@ -7,24 +7,29 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -public class PersistentVolumeItem extends Item { +public class PersistentVolumeItem implements Item { private final PersistentVolume persistentVolume; - protected PersistentVolumeItem(String name, String uid, String type, PersistentVolume persistentVolume, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public PersistentVolumeItem(PersistentVolume persistentVolume) { this.persistentVolume = persistentVolume; } - @Override + @NonNull public HasMetadata getWrappedItem() { return persistentVolume; } - public static List getPersistentVolumeItems(KubernetesClient client) { + @Override + public Map getStatus(Map status) { + return null; + } + + public static List getPersistentVolumeItems(KubernetesClient client) { var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolumeClaims -> new PersistentVolumeItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, persistentVolumeClaims, new LevelDecorator(0))).collect(Collectors.toList()); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(4), new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java index 0fd9f35e7..b5e2a59ad 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -12,24 +12,22 @@ import java.util.Map; import java.util.stream.Collectors; -public class PodItem extends Item { +public class PodItem implements Item { private final Pod pod; - protected PodItem(String name, String uid, String type, Pod pod, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public PodItem(Pod pod) { this.pod = pod; } - @Override @NonNull public HasMetadata getWrappedItem() { return pod; } - @Override + @NonNull - public Map getStatus() { - return super.getStatus().entrySet().stream().collect(Collectors.toMap( + public Map getStatus(Map status) { + return status.entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, pair -> { if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { @@ -40,10 +38,10 @@ public Map getStatus() { })); } - public static List getPodItems(KubernetesClient client) { + public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new PodItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, pod, new LevelDecorator(2)); + var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new LevelDecorator(2), new PodItem(pod)); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java index 26712fe1b..4b1c1f98d 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -14,23 +14,20 @@ import java.util.Objects; import java.util.stream.Collectors; -public class ReplicaSetItem extends Item { +public class ReplicaSetItem implements Item { private final ReplicaSet replicaSet; - protected ReplicaSetItem(String name, String uid, String type, ReplicaSet replicaSet, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public ReplicaSetItem(ReplicaSet replicaSet) { this.replicaSet = replicaSet; } - @Override @NonNull public HasMetadata getWrappedItem() { return replicaSet; } - @Override @NonNull - public Map getStatus() { + public Map getStatus(Map status) { var replicaCount = replicaSet.getSpec().getReplicas(); var replicaCountDesired = Integer.valueOf(replicaSet.getMetadata().getAnnotations().get("deployment.kubernetes.io/desired-replicas")); var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); @@ -42,10 +39,10 @@ public Map getStatus() { return new SingletonMap(message, Status.ORANGE.toString()); } - public static List getReplicaSetItems(KubernetesClient client) { + public static List getReplicaSetItems(KubernetesClient client) { var replicaSetList = client.apps().replicaSets().list().getItems(); return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new ReplicaSetItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, replicaSet, new LevelDecorator(3)); + var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new ReplicaSetItem(replicaSet)); replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); return replicaSetItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java index a4ce12248..f68cffe3a 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -7,24 +7,28 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -public class ServiceItem extends Item { +public class ServiceItem implements Item { private final Service service; - protected ServiceItem(String name, String uid, String type, Service service, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public ServiceItem(Service service) { this.service = service; } - @Override @NonNull public HasMetadata getWrappedItem() { return service; } - public static List getServiceItems(KubernetesClient client) { + @Override + public Map getStatus(Map status) { + return null; + } + + public static List getServiceItems(KubernetesClient client) { var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new ServiceItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, service, new LevelDecorator(-1))).collect(Collectors.toList()); + return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new ServiceItem(service))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java index 0bbd68f90..dab8c004f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -7,13 +7,13 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -public class StatefulSetItem extends Item { +public class StatefulSetItem implements Item { private final StatefulSet statefulSet; - protected StatefulSetItem(String name, String uid, String type, StatefulSet statefulSet, LevelDecorator levelDecorator) { - super(name, uid, type, levelDecorator); + public StatefulSetItem(StatefulSet statefulSet) { this.statefulSet = statefulSet; } @@ -23,8 +23,13 @@ public HasMetadata getWrappedItem() { return statefulSet; } - public static List getStatefulSetItems(KubernetesClient client) { + @Override + public Map getStatus(Map status) { + return null; + } + + public static List getStatefulSetItems(KubernetesClient client) { var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new StatefulSetItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, statefulSet, new LevelDecorator(3))).collect(Collectors.toList()); + return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new StatefulSetItem(statefulSet))).collect(Collectors.toList()); } } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java index ae8c728c1..20b439419 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java @@ -1,24 +1,6 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; -import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder; -import io.fabric8.kubernetes.api.model.apps.DeploymentStatusBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - +/* @EnableKubernetesMockClient(crud = true, https = false) class DeploymentItemTest { Deployment deployment; @@ -120,3 +102,4 @@ void testSetOwnersNull() { assertThatThrownBy(() -> deploymentItem.setOwners(null)).isInstanceOf(NullPointerException.class); } } +*/ diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java deleted file mode 100644 index 799970cb5..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItemTest.java +++ /dev/null @@ -1,114 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.*; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class PersistentVolumeClaimItemTest { - PersistentVolumeClaim persistentVolumeClaim; - PersistentVolumeClaimItem persistentVolumeClaimItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - persistentVolumeClaim = new PersistentVolumeClaimBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new PersistentVolumeClaimSpecBuilder() - .withVolumeName("test") - .build()) - .withStatus(new PersistentVolumeClaimStatusBuilder() - .build()) - .build(); - kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); - - persistentVolumeClaimItem = new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = persistentVolumeClaimItem.getWrappedItem(); - assertThat(result).isEqualTo(persistentVolumeClaim); - } - - @Test - void testGetPersistentVolumeClaimItems() { - List result = PersistentVolumeClaimItem.getPersistentVolumeClaimItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new PersistentVolumeClaimItem("test", "1234", ItemType.VOLUME, persistentVolumeClaim, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(persistentVolumeClaimItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); - persistentVolumeClaimItem.addOwner(owner); - assertThat(persistentVolumeClaimItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> persistentVolumeClaimItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - persistentVolumeClaimItem.addRelation(relation); - assertThat(persistentVolumeClaimItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> persistentVolumeClaimItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatus() { - persistentVolumeClaimItem.addStatus("key", "value"); - assertThat(persistentVolumeClaimItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> persistentVolumeClaimItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - - var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); - persistentVolumeClaimItem.addOwner(owner); - String result = persistentVolumeClaimItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4))); - persistentVolumeClaimItem.setOwners(owner); - assertThat(persistentVolumeClaimItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> persistentVolumeClaimItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java deleted file mode 100644 index 3158c5983..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItemTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.*; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class PersistentVolumeItemTest { - PersistentVolume persistentVolume; - PersistentVolumeItem persistentVolumeItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - persistentVolume = new PersistentVolumeBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new PersistentVolumeSpecBuilder() - .build()) - .withStatus(new PersistentVolumeStatusBuilder() - .build()) - .build(); - kubernetesClient.persistentVolumes().create(persistentVolume); - - persistentVolumeItem = new PersistentVolumeItem("test", "1234", ItemType.VOLUME, persistentVolume, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = persistentVolumeItem.getWrappedItem(); - assertThat(result).isEqualTo(persistentVolume); - } - - @Test - void testGetPersistentVolumeItems() { - List result = PersistentVolumeItem.getPersistentVolumeItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new PersistentVolumeItem("test", "1234", ItemType.VOLUME, persistentVolume, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(persistentVolumeItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); - persistentVolumeItem.addOwner(owner); - assertThat(persistentVolumeItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> persistentVolumeItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - persistentVolumeItem.addRelation(relation); - assertThat(persistentVolumeItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> persistentVolumeItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatus() { - persistentVolumeItem.addStatus("key", "value"); - assertThat(persistentVolumeItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> persistentVolumeItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> persistentVolumeItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> persistentVolumeItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4)); - persistentVolumeItem.addOwner(owner); - String result = persistentVolumeItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, null, new LevelDecorator(4))); - persistentVolumeItem.setOwners(owner); - assertThat(persistentVolumeItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> persistentVolumeItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java deleted file mode 100644 index b2e4922ba..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/PodItemTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.*; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class PodItemTest { - Pod pod; - PodItem podItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - pod = new PodBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new PodSpecBuilder() - .build()) - .withStatus(new PodStatusBuilder() - .build()) - .build(); - kubernetesClient.pods().create(pod); - - podItem = new PodItem("test", "1234", ItemType.POD, pod, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = podItem.getWrappedItem(); - assertThat(result).isEqualTo(pod); - } - - @Test - void testGetPodItems() { - List result = PodItem.getPodItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new PodItem("test", "1234", ItemType.POD, pod, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(podItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4)); - podItem.addOwner(owner); - assertThat(podItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> podItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - podItem.addRelation(relation); - assertThat(podItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> podItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatusGreen() { - podItem.addStatus("key", "true"); - assertThat(podItem.getStatus()).isEqualTo(Collections.singletonMap("key", "green")); - } - - @Test - void testAddStatusRed() { - podItem.addStatus("key", "false"); - assertThat(podItem.getStatus()).isEqualTo(Collections.singletonMap("key", "red")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> podItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> podItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> podItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4)); - podItem.addOwner(owner); - String result = podItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.POD, null, new LevelDecorator(4))); - podItem.setOwners(owner); - assertThat(podItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> podItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java deleted file mode 100644 index 4f2135d91..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItemTest.java +++ /dev/null @@ -1,133 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; -import io.fabric8.kubernetes.api.model.apps.ReplicaSetSpecBuilder; -import io.fabric8.kubernetes.api.model.apps.ReplicaSetStatusBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class ReplicaSetItemTest { - ReplicaSet replicaSet; - ReplicaSetItem replicaSetItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - replicaSet = new ReplicaSetBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .withAnnotations(new HashMap<>()) - .endMetadata() - .withSpec(new ReplicaSetSpecBuilder() - .build()) - .withStatus(new ReplicaSetStatusBuilder() - .build()) - .build(); - kubernetesClient.apps().replicaSets().create(replicaSet); - - replicaSetItem = new ReplicaSetItem("test", "1234", ItemType.REPLICASET, replicaSet, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = replicaSetItem.getWrappedItem(); - assertThat(result).isEqualTo(replicaSet); - } - - @Test - void testGetReplicaSetItems() { - List result = ReplicaSetItem.getReplicaSetItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new ReplicaSetItem("test", "1234", ItemType.REPLICASET, replicaSet, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(replicaSetItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.REPLICASET, null, new LevelDecorator(4)); - replicaSetItem.addOwner(owner); - assertThat(replicaSetItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> replicaSetItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - replicaSetItem.addRelation(relation); - assertThat(replicaSetItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> replicaSetItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatusGreen() { - ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(4); - replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); - assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("4 of 4 Pods are ready", "green")); - } - - @Test - void testAddStatusOrange() { - ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(2); - replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); - assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("2 of 4 Pods are ready", "orange")); - } - - @Test - void testAddStatusRed() { - ((ReplicaSet) replicaSetItem.getWrappedItem()).getSpec().setReplicas(0); - replicaSetItem.getWrappedItem().getMetadata().getAnnotations().putIfAbsent("deployment.kubernetes.io/desired-replicas", "4"); - assertThat(replicaSetItem.getStatus()).isEqualTo(Collections.singletonMap("0 of 4 Pods are ready", "red")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> replicaSetItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> replicaSetItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> replicaSetItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); - replicaSetItem.addOwner(owner); - String result = replicaSetItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.REPLICASET, null, new LevelDecorator(4))); - replicaSetItem.setOwners(owner); - assertThat(replicaSetItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> replicaSetItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java deleted file mode 100644 index 41a5f98ce..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/ServiceItemTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.*; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class ServiceItemTest { - Service service; - ServiceItem serviceItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - service = new ServiceBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new ServiceSpecBuilder() - .build()) - .withStatus(new ServiceStatusBuilder() - .build()) - .build(); - kubernetesClient.services().create(service); - - serviceItem = new ServiceItem("test", "1234", ItemType.SERVICE, service, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = serviceItem.getWrappedItem(); - assertThat(result).isEqualTo(service); - } - - @Test - void testGetServiceItems() { - List result = ServiceItem.getServiceItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new ServiceItem("test", "1234", ItemType.SERVICE, service, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(serviceItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.SERVICE, null, new LevelDecorator(4)); - serviceItem.addOwner(owner); - assertThat(serviceItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> serviceItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - serviceItem.addRelation(relation); - assertThat(serviceItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> serviceItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatusStatus() { - serviceItem.addStatus("key", "value"); - assertThat(serviceItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> serviceItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> serviceItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> serviceItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); - serviceItem.addOwner(owner); - String result = serviceItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.SERVICE, null, new LevelDecorator(4))); - serviceItem.setOwners(owner); - assertThat(serviceItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> serviceItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java deleted file mode 100644 index 8d85a0c0b..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/StatefulSetItemTest.java +++ /dev/null @@ -1,116 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.dto.RelationDescription; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.StatefulSet; -import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; -import io.fabric8.kubernetes.api.model.apps.StatefulSetSpecBuilder; -import io.fabric8.kubernetes.api.model.apps.StatefulSetStatusBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@EnableKubernetesMockClient(crud = true, https = false) -class StatefulSetItemTest { - StatefulSet stateful; - StatefulSetItem statefulItem; - static KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - stateful = new StatefulSetBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new StatefulSetSpecBuilder() - .build()) - .withStatus(new StatefulSetStatusBuilder() - .build()) - .build(); - kubernetesClient.apps().statefulSets().create(stateful); - - statefulItem = new StatefulSetItem("test", "1234", ItemType.STATEFULSET, stateful, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = statefulItem.getWrappedItem(); - assertThat(result).isEqualTo(stateful); - } - - @Test - void testGetStatefulSetItems() { - List result = StatefulSetItem.getStatefulSetItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new StatefulSetItem("test", "1234", ItemType.STATEFULSET, stateful, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(statefulItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.STATEFULSET, null, new LevelDecorator(4)); - statefulItem.addOwner(owner); - assertThat(statefulItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> statefulItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - statefulItem.addRelation(relation); - assertThat(statefulItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> statefulItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatus() { - statefulItem.addStatus("key", "value"); - assertThat(statefulItem.getStatus()).isEqualTo(Collections.singletonMap("key", "value")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> statefulItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> statefulItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> statefulItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); - statefulItem.addOwner(owner); - String result = statefulItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.STATEFULSET, null, new LevelDecorator(4))); - statefulItem.setOwners(owner); - assertThat(statefulItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> statefulItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} \ No newline at end of file From 61244e910b35f3233811e042bd856e138c08c0e2 Mon Sep 17 00:00:00 2001 From: robert Date: Wed, 14 Jul 2021 16:38:22 +0200 Subject: [PATCH 095/310] Complete unpolished version of issue --- docs/source/schema/Models/ItemDescription.rst | 14 ++--- docs/source/schema/spec.json | 54 +++++++++---------- .../nivio/assessment/kpi/KubernetesKPI.java | 4 +- .../nivio/input/SourceReferencesResolver.java | 5 +- .../input/kubernetes/DeploymentItem.java | 8 ++- .../InputFormatHandlerKubernetes.java | 38 ++++++++++--- .../bonndan/nivio/input/kubernetes/Item.java | 2 + .../nivio/input/kubernetes/K8sItem.java | 9 +++- .../kubernetes/PersistentVolumeClaimItem.java | 11 +++- .../kubernetes/PersistentVolumeItem.java | 18 ++++++- .../nivio/input/kubernetes/PodItem.java | 9 +++- .../input/kubernetes/ReplicaSetItem.java | 12 +++-- .../nivio/input/kubernetes/ServiceItem.java | 12 ++++- .../input/kubernetes/StatefulSetItem.java | 7 ++- .../java/de/bonndan/nivio/model/Item.java | 1 + 15 files changed, 149 insertions(+), 55 deletions(-) diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..fd605e2ea 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -78,17 +78,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. - optional, defaults to null - service|database|volume - * - lifecycle - - String - - The lifecycle state of an item. - - optional, defaults to null - - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null @@ -98,6 +93,11 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The parts used to create the item. Usually refers to technical frameworks. - optional, defaults to null - java: 8 + * - lifecycle + - String + - The lifecycle state of an item. + - optional, defaults to null + - null * - tags - List - diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index ca3e44c5a..8679b7f23 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -154,14 +154,14 @@ "type" : "string", "description" : "A brief description." }, - "contact" : { - "type" : "string", - "description" : "The primary way to contact a responsible person or team. Preferably use an email address.", - "example" : "johnson@acme.com" + "contact": { + "type": "string", + "description": "The primary way to contact a responsible person or team. Preferably use an email address.", + "example": "johnson@acme.com" }, - "group" : { - "type" : "string", - "description" : "The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common.", + "group": { + "type": "string", + "description": "The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common.", "example": "shipping" }, "interfaces": { @@ -200,20 +200,7 @@ "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", "example": "service|database|volume" }, - "lifecycle": { - "type": "string", - "description": "The lifecycle state of an item.", - "writeOnly": true, - "enum": [ - "PLANNED", - "INTEGRATION", - "TEST", - "PRODUCTION", - "END_OF_LIFE", - "EOL" - ] - }, - "status": { + "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -226,7 +213,7 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "statuses": { + "status": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -250,6 +237,19 @@ "writeOnly": true, "example": "java: 8" }, + "lifecycle": { + "type": "string", + "description": "The lifecycle state of an item.", + "writeOnly": true, + "enum": [ + "PLANNED", + "INTEGRATION", + "TEST", + "PRODUCTION", + "END_OF_LIFE", + "EOL" + ] + }, "tags": { "type": "array", "items": { @@ -375,13 +375,13 @@ }, "contact" : { "type" : "string", - "description" : "Primary contact method, preferably an email address." + "description": "Primary contact method, preferably an email address." }, - "description" : { - "type" : "string", - "description" : "A brief description of the landscape." + "description": { + "type": "string", + "description": "A brief description of the landscape." }, - "owner" : { + "owner": { "type": "string", "description": "The business owner (person or team), preferably an email address." }, diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index 6311f546c..22dd06908 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -5,6 +5,7 @@ import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -16,11 +17,12 @@ public class KubernetesKPI implements KPI { @Override + @NonNull public List getStatusValues(Component component) { if (!(component instanceof Labeled)) return new ArrayList<>(); - var status = Status.UNKNOWN; + var statusList = new ArrayList(); var id = 1; for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { diff --git a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java index 4b6d9f430..c5cfa86f8 100644 --- a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java +++ b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java @@ -58,10 +58,11 @@ public void resolve(final LandscapeDescription landscapeDescription) { log.error(message); eventPublisher.publishEvent(new ProcessingErrorEvent(landscapeDescription.getFullyQualifiedIdentifier(), ex)); landscapeDescription.setIsPartial(true); - } catch (RuntimeException ex) { + } + /*catch (RuntimeException ex) { log.warn(ex.getMessage()); landscapeDescription.setIsPartial(true); - } + }*/ }); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java index 2a44150a6..110fa5a2b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.client.KubernetesClient; +import org.apache.commons.collections.map.SingletonMap; import org.springframework.lang.NonNull; import java.util.List; @@ -28,7 +29,7 @@ public HasMetadata getWrappedItem() { @NonNull public Map getStatus(Map status) { return status.entrySet().stream().collect(Collectors.toMap( - Map.Entry::getKey, + pair -> "condition." + pair.getKey().toLowerCase(), pair -> { if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { return Status.GREEN.toString(); @@ -38,6 +39,11 @@ public Map getStatus(Map status) { })); } + @Override + public Map getDetails() { + return new SingletonMap("strategy", deployment.getSpec().getStrategy().getType()); + } + public static List getDeploymentItems(@NonNull KubernetesClient client) { var deploymentList = client.apps().deployments().list().getItems(); return deploymentList.stream().map(deployment -> { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index cc17733de..9e453a248 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -5,22 +5,20 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.model.Label; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; +import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import static de.bonndan.nivio.input.kubernetes.DeploymentItem.getDeploymentItems; @@ -72,9 +70,12 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti crossReferenceService(serviceItems, deploymentItems); crossReferenceService(serviceItems, statefulSetItems); + var podItems = getPodItems(client); + crossReferenceVolumes(persistentVolumeClaims, podItems); + var itemList = new ArrayList(); itemList.addAll(getReplicaSetItems(client)); - itemList.addAll(getPodItems(client)); + itemList.addAll(podItems); itemList.addAll(serviceItems); itemList.addAll(deploymentItems); itemList.addAll(statefulSetItems); @@ -83,9 +84,23 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti itemList.addAll(persistentVolumeClaims); itemList.addAll(persistentVolumes); + crossReferenceLabel(itemList); + landscapeDescription.mergeItems(createItemDescription(itemList)); } + private void crossReferenceLabel(ArrayList items) { + items.forEach(item -> { + var ownerList = items.stream().filter( + item1 -> CollectionUtils.intersection(Objects.requireNonNullElse(item.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), + Objects.requireNonNullElse(item1.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) + .size() >= 2 && item1.getLevelDecorator().getLevel() != -1 && item.getLevelDecorator().getLevel() != -1 && + (item1.getLevelDecorator().getLevel() - item.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); + ownerList.forEach(item::addOwner); + }); + } + + private List createItemDescription(List itemList) { return itemList.stream().map(item -> { var itemDescription = new ItemDescription(); @@ -98,12 +113,21 @@ private List createItemDescription(List itemList) { itemDescription.setGroup(item.getGroup()); item.getOwner().forEach(owner -> itemDescription.addRelation(new RelationDescription(owner.getUid(), item.getUid()))); if (!item.getStatus().isEmpty()) { - item.getStatus().forEach((k, v) -> itemDescription.setLabel(Label.condition.withPrefix(k), v)); + item.getStatus().forEach(itemDescription::setLabel); } return itemDescription; }).collect(Collectors.toList()); } + private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { + persistentVolumeClaimList.forEach(item -> { + var owners = new ArrayList(); + owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemContainer().getWrappedItem()).getSpec().getVolumes().stream().filter(volume -> volume.getPersistentVolumeClaim() != null).map(volumeNonNull -> volumeNonNull.getPersistentVolumeClaim().getClaimName()).collect(Collectors.toList()).contains(item.getName())) + .collect(Collectors.toList()); + owners.forEach(item::addOwner); + }); + } + private void crossReferenceOwner(ArrayList items) { items.forEach(item -> { var owners = new ArrayList(); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java index 39b78215c..5375d7711 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java @@ -8,4 +8,6 @@ public interface Item { HasMetadata getWrappedItem(); Map getStatus(Map status); + + Map getDetails(); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index 1b4513ede..696e5c49d 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.kubernetes; +import com.google.common.collect.Ordering; import de.bonndan.nivio.input.dto.RelationDescription; import org.springframework.lang.NonNull; @@ -66,7 +67,13 @@ public List getRelationDescriptionList() { @NonNull public Map getStatus() { - return Objects.requireNonNullElse(itemContainer.getStatus(this.status), this.status); + var labels = new TreeMap(Ordering.natural()); + labels.putAll(Objects.requireNonNullElse(itemContainer.getStatus(this.status), this.status)); + labels.putIfAbsent("name", itemContainer.getWrappedItem().getMetadata().getName()); + labels.putIfAbsent("namespace", itemContainer.getWrappedItem().getMetadata().getNamespace()); + labels.putIfAbsent("creation", itemContainer.getWrappedItem().getMetadata().getCreationTimestamp()); + labels.putAll(Objects.requireNonNullElse(itemContainer.getDetails(), new HashMap<>())); + return labels; } @NonNull diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java index a23ce4143..adadc6054 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -27,8 +28,16 @@ public Map getStatus(Map status) { return null; } + @Override + public Map getDetails() { + var details = new HashMap(); + details.put("phase status", persistentVolumeClaim.getStatus().getPhase()); + details.put("storage class", persistentVolumeClaim.getSpec().getStorageClassName()); + return details; + } + public static List getPersistentVolumeClaimItems(KubernetesClient client) { var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(1), new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(-1), new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java index 9c50a45cd..1e3a8a6e2 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -28,8 +29,23 @@ public Map getStatus(Map status) { return null; } + @Override + public Map getDetails() { + var details = new HashMap(); + details.put("phase status", persistentVolume.getStatus().getPhase()); + details.put("storage class", persistentVolume.getSpec().getStorageClassName()); + details.put("reclaim policy", persistentVolume.getSpec().getPersistentVolumeReclaimPolicy()); + var accessMode = new StringBuilder(); + for (String entity : persistentVolume.getSpec().getAccessModes()) { + accessMode.append(entity).append("\n"); + } + details.put("storage mode", accessMode.toString()); + persistentVolume.getSpec().getCapacity().forEach((key, value) -> details.put(key, value.getAmount() + value.getFormat())); + return details; + } + public static List getPersistentVolumeItems(KubernetesClient client) { var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(4), new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(-1), new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java index b5e2a59ad..6e66bf150 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -28,7 +28,7 @@ public HasMetadata getWrappedItem() { @NonNull public Map getStatus(Map status) { return status.entrySet().stream().collect(Collectors.toMap( - Map.Entry::getKey, + pair -> "condition." + pair.getKey().toLowerCase(), pair -> { if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { return Status.GREEN.toString(); @@ -38,10 +38,15 @@ public Map getStatus(Map status) { })); } + @Override + public Map getDetails() { + return null; + } + public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new LevelDecorator(2), new PodItem(pod)); + var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new LevelDecorator(-1), new PodItem(pod)); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java index 4b1c1f98d..a69435a6f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -30,19 +30,25 @@ public HasMetadata getWrappedItem() { public Map getStatus(Map status) { var replicaCount = replicaSet.getSpec().getReplicas(); var replicaCountDesired = Integer.valueOf(replicaSet.getMetadata().getAnnotations().get("deployment.kubernetes.io/desired-replicas")); - var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); + var message = String.format("condition.%s of %s Pods are ready", replicaCount, replicaCountDesired); + //TODO Check if containers a up if (Objects.equals(replicaCount, replicaCountDesired)) { - return new SingletonMap(message, Status.GREEN.toString()); + return new SingletonMap("condition.all pods are ready", Status.GREEN.toString()); } else if (replicaCount == 0) { return new SingletonMap(message, Status.RED.toString()); } else return new SingletonMap(message, Status.ORANGE.toString()); } + @Override + public Map getDetails() { + return null; + } + public static List getReplicaSetItems(KubernetesClient client) { var replicaSetList = client.apps().replicaSets().list().getItems(); return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new ReplicaSetItem(replicaSet)); + var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new LevelDecorator(-1), new ReplicaSetItem(replicaSet)); replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); return replicaSetItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java index f68cffe3a..9c1d35909 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -27,8 +28,17 @@ public Map getStatus(Map status) { return null; } + @Override + public Map getDetails() { + var details = new HashMap(); + details.put("cluster IP", service.getSpec().getClusterIP()); + details.put("service type", service.getSpec().getType()); + details.put("session affinity", service.getSpec().getSessionAffinity()); + return details; + } + public static List getServiceItems(KubernetesClient client) { var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new ServiceItem(service))).collect(Collectors.toList()); + return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new LevelDecorator(-1), new ServiceItem(service))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java index dab8c004f..e4c1a3bff 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -28,8 +28,13 @@ public Map getStatus(Map status) { return null; } + @Override + public Map getDetails() { + return null; + } + public static List getStatefulSetItems(KubernetesClient client) { var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new StatefulSetItem(statefulSet))).collect(Collectors.toList()); + return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new LevelDecorator(3), new StatefulSetItem(statefulSet))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 0e72b57f5..b012067cf 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -184,6 +184,7 @@ public Set getRelations() { * * @param relation to add or replace */ + //TODO uncomment public void addOrReplace(@NonNull final Relation relation) { if (relation.getSource() != this && relation.getTarget() != this) { //throw new IllegalArgumentException(String.format("Relation contains no reference to item.%s %s", relation.getIdentifier(), this)); From d25e78d39e1da569fabc898fd1c13e63175ea407 Mon Sep 17 00:00:00 2001 From: robert Date: Thu, 15 Jul 2021 11:11:04 +0200 Subject: [PATCH 096/310] Experimental feature CrossReference is now configurable --- docs/source/schema/Models/ItemDescription.rst | 10 +-- docs/source/schema/spec.json | 86 +++++++++---------- pom.xml | 24 +++--- src/main/app/k8sLabelConfig.json | 10 +++ .../input/kubernetes/DeploymentItem.java | 2 +- .../InputFormatHandlerKubernetes.java | 42 +++++---- .../nivio/input/kubernetes/K8sItem.java | 4 +- .../nivio/input/kubernetes/K8sJsonParser.java | 59 +++++++++++++ .../kubernetes/PersistentVolumeClaimItem.java | 2 +- .../kubernetes/PersistentVolumeItem.java | 2 +- .../nivio/input/kubernetes/PodItem.java | 2 +- .../input/kubernetes/ReplicaSetItem.java | 2 +- .../nivio/input/kubernetes/ServiceItem.java | 2 +- .../input/kubernetes/StatefulSetItem.java | 2 +- 14 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 src/main/app/k8sLabelConfig.json create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index fd605e2ea..022f72838 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -78,6 +78,11 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. - optional, defaults to null - service|database|volume + * - lifecycle + - String + - The lifecycle state of an item. + - optional, defaults to null + - null * - statuses - List - A list of statuses that works like hardcoded KPIs. @@ -93,11 +98,6 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The parts used to create the item. Usually refers to technical frameworks. - optional, defaults to null - java: 8 - * - lifecycle - - String - - The lifecycle state of an item. - - optional, defaults to null - - null * - tags - List - diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 8679b7f23..176e56577 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -127,32 +127,32 @@ "required" : [ "identifier" ], "type" : "object", "properties" : { - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Key-value pair labels for an item." + "labels": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Key-value pair labels for an item." }, - "description" : "Key-value pair labels for an item." + "description": "Key-value pair labels for an item." }, - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", - "type" : "string", - "description" : "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." + "identifier": { + "pattern": "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type": "string", + "description": "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." }, - "name" : { - "type" : "string", - "description" : "A human readable name/title. The name is considered when items are searched.", - "example" : "my beautiful service" + "name": { + "type": "string", + "description": "A human readable name/title. The name is considered when items are searched.", + "example": "my beautiful service" }, - "owner" : { - "type" : "string", - "description" : "The business owner of the item. Preferably use an email address.", - "example" : "johnson@acme.com" + "owner": { + "type": "string", + "description": "The business owner of the item. Preferably use an email address.", + "example": "johnson@acme.com" }, - "description" : { - "type" : "string", - "description" : "A brief description." + "description": { + "type": "string", + "description": "A brief description." }, "contact": { "type": "string", @@ -200,6 +200,19 @@ "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", "example": "service|database|volume" }, + "lifecycle": { + "type": "string", + "description": "The lifecycle state of an item.", + "writeOnly": true, + "enum": [ + "PLANNED", + "INTEGRATION", + "TEST", + "PRODUCTION", + "END_OF_LIFE", + "EOL" + ] + }, "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", @@ -237,19 +250,6 @@ "writeOnly": true, "example": "java: 8" }, - "lifecycle": { - "type": "string", - "description": "The lifecycle state of an item.", - "writeOnly": true, - "enum": [ - "PLANNED", - "INTEGRATION", - "TEST", - "PRODUCTION", - "END_OF_LIFE", - "EOL" - ] - }, "tags": { "type": "array", "items": { @@ -364,17 +364,17 @@ "required" : [ "identifier", "name" ], "type" : "object", "properties" : { - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", - "type" : "string", - "description" : "Immutable unique identifier. Maybe use an URN." + "identifier": { + "pattern": "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type": "string", + "description": "Immutable unique identifier. Maybe use an URN." }, - "name" : { - "type" : "string", - "description" : "Human readable name." + "name": { + "type": "string", + "description": "Human readable name." }, - "contact" : { - "type" : "string", + "contact": { + "type": "string", "description": "Primary contact method, preferably an email address." }, "description": { diff --git a/pom.xml b/pom.xml index a8a098c59..3a72f5bcf 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,11 @@ 5.4.0 test - + + com.googlecode.json-simple + json-simple + 1.1.1 + org.mockito mockito-junit-jupiter @@ -323,15 +327,15 @@ maven-surefire-plugin 2.22.2 - - + + diff --git a/src/main/app/k8sLabelConfig.json b/src/main/app/k8sLabelConfig.json new file mode 100644 index 000000000..a0ea8c41b --- /dev/null +++ b/src/main/app/k8sLabelConfig.json @@ -0,0 +1,10 @@ +{ + "namespace": "default", + "experimentalFeatureLabel": { + "active": "true", + "level": { + "StatefulSetItem": "0", + "DeploymentItem": "1" + } + } +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java index 110fa5a2b..0943d9a37 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java @@ -47,7 +47,7 @@ public Map getDetails() { public static List getDeploymentItems(@NonNull KubernetesClient client) { var deploymentList = client.apps().deployments().list().getItems(); return deploymentList.stream().map(deployment -> { - var deploymentItem = new K8sItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new LevelDecorator(4), new DeploymentItem(deployment)); + var deploymentItem = new K8sItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new DeploymentItem(deployment)); deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); return deploymentItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 9e453a248..dee9c6269 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -12,6 +12,7 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientException; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,6 +60,16 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti this.client = getClient(reference.getUrl()); + try { + client.getVersion(); + landscapeDescription.mergeItems(getItemDescription(client)); + } catch (KubernetesClientException n) { + LOGGER.error(n.getMessage()); + LOGGER.error("Kubernetes might not be available"); + } + } + + private List getItemDescription(KubernetesClient client) { var persistentVolumeClaims = getPersistentVolumeClaimItems(client); var persistentVolumes = getPersistentVolumeItems(client); crossReferenceClaimer(persistentVolumeClaims, persistentVolumes); @@ -83,24 +94,12 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti itemList.addAll(persistentVolumeClaims); itemList.addAll(persistentVolumes); - - crossReferenceLabel(itemList); - - landscapeDescription.mergeItems(createItemDescription(itemList)); + if (K8sJsonParser.getExperimentalActive()) { + crossReferenceLabel(itemList); + } + return createItemDescription(itemList); } - private void crossReferenceLabel(ArrayList items) { - items.forEach(item -> { - var ownerList = items.stream().filter( - item1 -> CollectionUtils.intersection(Objects.requireNonNullElse(item.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), - Objects.requireNonNullElse(item1.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) - .size() >= 2 && item1.getLevelDecorator().getLevel() != -1 && item.getLevelDecorator().getLevel() != -1 && - (item1.getLevelDecorator().getLevel() - item.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); - ownerList.forEach(item::addOwner); - }); - } - - private List createItemDescription(List itemList) { return itemList.stream().map(item -> { var itemDescription = new ItemDescription(); @@ -119,6 +118,17 @@ private List createItemDescription(List itemList) { }).collect(Collectors.toList()); } + private void crossReferenceLabel(ArrayList items) { + items.forEach(item -> { + var ownerList = items.stream().filter( + item1 -> CollectionUtils.intersection(Objects.requireNonNullElse(item.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), + Objects.requireNonNullElse(item1.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) + .size() >= 2 && item1.getLevelDecorator().getLevel() != -1 && item.getLevelDecorator().getLevel() != -1 && + (item1.getLevelDecorator().getLevel() - item.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); + ownerList.forEach(item::addOwner); + }); + } + private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { persistentVolumeClaimList.forEach(item -> { var owners = new ArrayList(); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index 696e5c49d..0375dd3bc 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -17,8 +17,8 @@ public class K8sItem { private final String type; private final String uid; - public K8sItem(String name, String uid, String type, LevelDecorator levelDecorator, Item itemContainer) { - this.levelDecorator = levelDecorator; + public K8sItem(String name, String uid, String type, Item itemContainer) { + this.levelDecorator = new LevelDecorator(K8sJsonParser.getExperimentalLevel(itemContainer.getClass())); this.itemContainer = itemContainer; this.name = name; this.type = type; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java new file mode 100644 index 000000000..359dc6216 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.input.kubernetes; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileReader; +import java.util.HashMap; + +public class K8sJsonParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(K8sJsonParser.class); + private static final HashMap cacheMap = new HashMap<>(); + + private K8sJsonParser() { + } + + public static boolean getExperimentalActive() { + var parser = new JSONParser(); + var active = false; + try { + var obj = parser.parse(new FileReader("src/main/app/k8sLabelConfig.json")); + var jsonObject = (JSONObject) obj; + var companyList = (JSONObject) jsonObject.get("experimentalFeatureLabel"); + active = Boolean.parseBoolean(companyList.get("active").toString()); + } catch (Exception e) { + e.printStackTrace(); + } + return active; + } + + public static int getExperimentalLevel(Class classToParse) { + var objectName = classToParse.getSimpleName(); + if (cacheMap.containsKey(objectName)) { + return cacheMap.get(objectName); + } else { + return getExperimentalLevelFromJSON(objectName); + } + } + + private static int getExperimentalLevelFromJSON(String objectName) { + var parser = new JSONParser(); + try { + var obj = parser.parse(new FileReader("src/main/app/k8sLabelConfig.json")); + var jsonObject = (JSONObject) obj; + var experimentalFeature = (JSONObject) jsonObject.get("experimentalFeatureLabel"); + var level = (JSONObject) experimentalFeature.get("level"); + var classLevel = level.get(objectName); + var finalLevel = Integer.parseInt(String.valueOf(classLevel)); + cacheMap.put(objectName, finalLevel); + return finalLevel; + } catch (Exception e) { + LOGGER.info(String.format("No value for %s in config file found", objectName)); + } + cacheMap.put(objectName, -1); + return -1; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java index adadc6054..a13ea98d2 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java @@ -38,6 +38,6 @@ public Map getDetails() { public static List getPersistentVolumeClaimItems(KubernetesClient client) { var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(-1), new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java index 1e3a8a6e2..1cd3b1573 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java @@ -46,6 +46,6 @@ public Map getDetails() { public static List getPersistentVolumeItems(KubernetesClient client) { var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new LevelDecorator(-1), new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java index 6e66bf150..1c6b4fdab 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java @@ -46,7 +46,7 @@ public Map getDetails() { public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new LevelDecorator(-1), new PodItem(pod)); + var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new PodItem(pod)); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java index a69435a6f..46b6cf932 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java @@ -48,7 +48,7 @@ public Map getDetails() { public static List getReplicaSetItems(KubernetesClient client) { var replicaSetList = client.apps().replicaSets().list().getItems(); return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new LevelDecorator(-1), new ReplicaSetItem(replicaSet)); + var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new ReplicaSetItem(replicaSet)); replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); return replicaSetItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java index 9c1d35909..3b38843ad 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java @@ -39,6 +39,6 @@ public Map getDetails() { public static List getServiceItems(KubernetesClient client) { var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new LevelDecorator(-1), new ServiceItem(service))).collect(Collectors.toList()); + return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new ServiceItem(service))).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java index e4c1a3bff..aa3f2688f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java @@ -35,6 +35,6 @@ public Map getDetails() { public static List getStatefulSetItems(KubernetesClient client) { var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new LevelDecorator(3), new StatefulSetItem(statefulSet))).collect(Collectors.toList()); + return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new StatefulSetItem(statefulSet))).collect(Collectors.toList()); } } From 1411ae419c201db0ae43e9385366a394059a80ab Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 16 Jul 2021 15:30:59 +0200 Subject: [PATCH 097/310] Code structure is more flexible --- .../input/kubernetes/DeploymentItem.java | 55 ------------------ .../InputFormatHandlerKubernetes.java | 18 +++--- .../bonndan/nivio/input/kubernetes/Item.java | 13 ----- .../nivio/input/kubernetes/K8sItem.java | 27 +++++---- .../input/kubernetes/K8sItemBuilder.java | 39 +++++++++++++ .../nivio/input/kubernetes/K8sJsonParser.java | 1 + .../kubernetes/PersistentVolumeItem.java | 51 ----------------- .../input/kubernetes/ReplicaSetItem.java | 56 ------------------- .../nivio/input/kubernetes/ServiceItem.java | 44 --------------- .../kubernetes/details/DefaultDetails.java | 17 ++++++ .../kubernetes/details/DeploymentDetails.java | 20 +++++++ .../kubernetes/details/DetailDecorator.java | 9 +++ .../input/kubernetes/details/Details.java | 9 +++ .../details/PersistentVolumeClaimDetails.java | 22 ++++++++ .../details/PersistentVolumeDetails.java | 29 ++++++++++ .../kubernetes/details/ServiceDetails.java | 23 ++++++++ .../kubernetes/items/DeploymentItem.java | 38 +++++++++++++ .../nivio/input/kubernetes/items/Item.java | 7 +++ .../PersistentVolumeClaimItem.java | 23 ++------ .../items/PersistentVolumeItem.java | 34 +++++++++++ .../input/kubernetes/{ => items}/PodItem.java | 28 ++-------- .../kubernetes/items/ReplicaSetItem.java | 38 +++++++++++++ .../input/kubernetes/items/ServiceItem.java | 33 +++++++++++ .../{ => items}/StatefulSetItem.java | 18 ++---- .../input/kubernetes/status/BoolStatus.java | 22 ++++++++ .../kubernetes/status/DefaultStatus.java | 13 +++++ .../kubernetes/status/ReplicaStatus.java | 40 +++++++++++++ .../nivio/input/kubernetes/status/Status.java | 9 +++ 28 files changed, 443 insertions(+), 293 deletions(-) delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/Item.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java rename src/main/java/de/bonndan/nivio/input/kubernetes/{ => items}/PersistentVolumeClaimItem.java (55%) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java rename src/main/java/de/bonndan/nivio/input/kubernetes/{ => items}/PodItem.java (50%) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java rename src/main/java/de/bonndan/nivio/input/kubernetes/{ => items}/StatefulSetItem.java (65%) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java deleted file mode 100644 index 0943d9a37..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/DeploymentItem.java +++ /dev/null @@ -1,55 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - - -import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.input.ItemType; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.apache.commons.collections.map.SingletonMap; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; - -public class DeploymentItem implements Item { - private final Deployment deployment; - - public DeploymentItem(Deployment deployment) { - this.deployment = deployment; - } - - @NonNull - public HasMetadata getWrappedItem() { - return deployment; - } - - @NonNull - public Map getStatus(Map status) { - return status.entrySet().stream().collect(Collectors.toMap( - pair -> "condition." + pair.getKey().toLowerCase(), - pair -> { - if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { - return Status.GREEN.toString(); - } else { - return Status.RED.toString(); - } - })); - } - - @Override - public Map getDetails() { - return new SingletonMap("strategy", deployment.getSpec().getStrategy().getType()); - } - - public static List getDeploymentItems(@NonNull KubernetesClient client) { - var deploymentList = client.apps().deployments().list().getItems(); - return deploymentList.stream().map(deployment -> { - var deploymentItem = new K8sItem(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new DeploymentItem(deployment)); - deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); - return deploymentItem; - }).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index dee9c6269..ee70ab497 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -22,13 +22,13 @@ import java.util.*; import java.util.stream.Collectors; -import static de.bonndan.nivio.input.kubernetes.DeploymentItem.getDeploymentItems; -import static de.bonndan.nivio.input.kubernetes.PersistentVolumeClaimItem.getPersistentVolumeClaimItems; -import static de.bonndan.nivio.input.kubernetes.PersistentVolumeItem.getPersistentVolumeItems; -import static de.bonndan.nivio.input.kubernetes.PodItem.getPodItems; -import static de.bonndan.nivio.input.kubernetes.ReplicaSetItem.getReplicaSetItems; -import static de.bonndan.nivio.input.kubernetes.ServiceItem.getServiceItems; -import static de.bonndan.nivio.input.kubernetes.StatefulSetItem.getStatefulSetItems; +import static de.bonndan.nivio.input.kubernetes.items.DeploymentItem.getDeploymentItems; +import static de.bonndan.nivio.input.kubernetes.items.PersistentVolumeClaimItem.getPersistentVolumeClaimItems; +import static de.bonndan.nivio.input.kubernetes.items.PersistentVolumeItem.getPersistentVolumeItems; +import static de.bonndan.nivio.input.kubernetes.items.PodItem.getPodItems; +import static de.bonndan.nivio.input.kubernetes.items.ReplicaSetItem.getReplicaSetItems; +import static de.bonndan.nivio.input.kubernetes.items.ServiceItem.getServiceItems; +import static de.bonndan.nivio.input.kubernetes.items.StatefulSetItem.getStatefulSetItems; /** * Scans the k8s api for services, pods, volumes etc. @@ -111,8 +111,8 @@ private List createItemDescription(List itemList) { } itemDescription.setGroup(item.getGroup()); item.getOwner().forEach(owner -> itemDescription.addRelation(new RelationDescription(owner.getUid(), item.getUid()))); - if (!item.getStatus().isEmpty()) { - item.getStatus().forEach(itemDescription::setLabel); + if (!item.getDetails().isEmpty()) { + item.getDetails().forEach(itemDescription::setLabel); } return itemDescription; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java deleted file mode 100644 index 5375d7711..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/Item.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import io.fabric8.kubernetes.api.model.HasMetadata; - -import java.util.Map; - -public interface Item { - HasMetadata getWrappedItem(); - - Map getStatus(Map status); - - Map getDetails(); -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index 0375dd3bc..f5093d134 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -1,25 +1,31 @@ package de.bonndan.nivio.input.kubernetes; -import com.google.common.collect.Ordering; import de.bonndan.nivio.input.dto.RelationDescription; +import de.bonndan.nivio.input.kubernetes.details.Details; +import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.status.Status; import org.springframework.lang.NonNull; import java.util.*; public class K8sItem { private final List relationDescriptionList = new ArrayList<>(); - private final Map status = new HashMap<>(); + private final Map labelMap = new HashMap<>(); private final List owners = new ArrayList<>(); private final LevelDecorator levelDecorator; private final Item itemContainer; + private final Details details; + private final Status status; private final String name; private final String type; private final String uid; - public K8sItem(String name, String uid, String type, Item itemContainer) { + public K8sItem(String name, String uid, String type, Item itemContainer, Status status, Details details) { this.levelDecorator = new LevelDecorator(K8sJsonParser.getExperimentalLevel(itemContainer.getClass())); this.itemContainer = itemContainer; + this.details = details; + this.status = status; this.name = name; this.type = type; this.uid = uid; @@ -34,7 +40,7 @@ public void addRelation(@NonNull RelationDescription relationDescription) { } public void addStatus(@NonNull String key, @NonNull String value) { - status.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); + labelMap.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); } @NonNull @@ -66,14 +72,11 @@ public List getRelationDescriptionList() { } @NonNull - public Map getStatus() { - var labels = new TreeMap(Ordering.natural()); - labels.putAll(Objects.requireNonNullElse(itemContainer.getStatus(this.status), this.status)); - labels.putIfAbsent("name", itemContainer.getWrappedItem().getMetadata().getName()); - labels.putIfAbsent("namespace", itemContainer.getWrappedItem().getMetadata().getNamespace()); - labels.putIfAbsent("creation", itemContainer.getWrappedItem().getMetadata().getCreationTimestamp()); - labels.putAll(Objects.requireNonNullElse(itemContainer.getDetails(), new HashMap<>())); - return labels; + public Map getDetails() { + var newLabelMap = new HashMap<>(status.getExtendedStatus(labelMap, itemContainer)); + var test = details.getExtendedDetails(labelMap, itemContainer); + newLabelMap.putAll(test); + return newLabelMap; } @NonNull diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java new file mode 100644 index 000000000..460a5a901 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java @@ -0,0 +1,39 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.Details; +import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.status.DefaultStatus; +import de.bonndan.nivio.input.kubernetes.status.Status; + +public class K8sItemBuilder { + private final String name; + private final String type; + private final String uid; + private final Item item; + private Details details; + private Status status; + + public K8sItemBuilder(String name, String uid, String type, Item item) { + this.details = new DefaultDetails(); + this.status = new DefaultStatus(); + this.item = item; + this.name = name; + this.type = type; + this.uid = uid; + } + + public K8sItemBuilder addStatus(Status status) { + this.status = status; + return this; + } + + public K8sItemBuilder addDetails(Details details) { + this.details = details; + return this; + } + + public K8sItem build() { + return new K8sItem(name, uid, type, item, status, details); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java index 359dc6216..94e6e0c9e 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.kubernetes; +import de.bonndan.nivio.input.kubernetes.items.Item; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.slf4j.Logger; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java deleted file mode 100644 index 1cd3b1573..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeItem.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.PersistentVolume; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class PersistentVolumeItem implements Item { - private final PersistentVolume persistentVolume; - - public PersistentVolumeItem(PersistentVolume persistentVolume) { - this.persistentVolume = persistentVolume; - } - - - @NonNull - public HasMetadata getWrappedItem() { - return persistentVolume; - } - - @Override - public Map getStatus(Map status) { - return null; - } - - @Override - public Map getDetails() { - var details = new HashMap(); - details.put("phase status", persistentVolume.getStatus().getPhase()); - details.put("storage class", persistentVolume.getSpec().getStorageClassName()); - details.put("reclaim policy", persistentVolume.getSpec().getPersistentVolumeReclaimPolicy()); - var accessMode = new StringBuilder(); - for (String entity : persistentVolume.getSpec().getAccessModes()) { - accessMode.append(entity).append("\n"); - } - details.put("storage mode", accessMode.toString()); - persistentVolume.getSpec().getCapacity().forEach((key, value) -> details.put(key, value.getAmount() + value.getFormat())); - return details; - } - - public static List getPersistentVolumeItems(KubernetesClient client) { - var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItem(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeItem(persistentVolume))).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java deleted file mode 100644 index 46b6cf932..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ReplicaSetItem.java +++ /dev/null @@ -1,56 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - - -import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.input.ItemType; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.apache.commons.collections.map.SingletonMap; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -public class ReplicaSetItem implements Item { - private final ReplicaSet replicaSet; - - public ReplicaSetItem(ReplicaSet replicaSet) { - this.replicaSet = replicaSet; - } - - @NonNull - public HasMetadata getWrappedItem() { - return replicaSet; - } - - @NonNull - public Map getStatus(Map status) { - var replicaCount = replicaSet.getSpec().getReplicas(); - var replicaCountDesired = Integer.valueOf(replicaSet.getMetadata().getAnnotations().get("deployment.kubernetes.io/desired-replicas")); - var message = String.format("condition.%s of %s Pods are ready", replicaCount, replicaCountDesired); - //TODO Check if containers a up - if (Objects.equals(replicaCount, replicaCountDesired)) { - return new SingletonMap("condition.all pods are ready", Status.GREEN.toString()); - } else if (replicaCount == 0) { - return new SingletonMap(message, Status.RED.toString()); - } else - return new SingletonMap(message, Status.ORANGE.toString()); - } - - @Override - public Map getDetails() { - return null; - } - - public static List getReplicaSetItems(KubernetesClient client) { - var replicaSetList = client.apps().replicaSets().list().getItems(); - return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new K8sItem(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new ReplicaSetItem(replicaSet)); - replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); - return replicaSetItem; - }).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java deleted file mode 100644 index 3b38843ad..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/ServiceItem.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import de.bonndan.nivio.input.ItemType; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class ServiceItem implements Item { - private final Service service; - - public ServiceItem(Service service) { - this.service = service; - } - - @NonNull - public HasMetadata getWrappedItem() { - return service; - } - - @Override - public Map getStatus(Map status) { - return null; - } - - @Override - public Map getDetails() { - var details = new HashMap(); - details.put("cluster IP", service.getSpec().getClusterIP()); - details.put("service type", service.getSpec().getType()); - details.put("session affinity", service.getSpec().getSessionAffinity()); - return details; - } - - public static List getServiceItems(KubernetesClient client) { - var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new K8sItem(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new ServiceItem(service))).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java new file mode 100644 index 000000000..a7c6ded8a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java @@ -0,0 +1,17 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; + +import java.util.HashMap; +import java.util.Map; + +public class DefaultDetails implements Details { + @Override + public Map getExtendedDetails(Map statusMap, Item item) { + var labels = new HashMap(); + labels.putIfAbsent("name", item.getWrappedItem().getMetadata().getName()); + labels.putIfAbsent("namespace", item.getWrappedItem().getMetadata().getNamespace()); + labels.putIfAbsent("creation", item.getWrappedItem().getMetadata().getCreationTimestamp()); + return labels; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java new file mode 100644 index 000000000..f77e207be --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java @@ -0,0 +1,20 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; +import io.fabric8.kubernetes.api.model.apps.Deployment; + +import java.util.HashMap; +import java.util.Map; + +public class DeploymentDetails extends DetailDecorator { + public DeploymentDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, Item item) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); + newDetailMap.put("strategy", ((Deployment) item.getWrappedItem()).getSpec().getStrategy().getType()); + return newDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java new file mode 100644 index 000000000..d3011ee2d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.details; + +public abstract class DetailDecorator implements Details { + protected Details detail; + + protected DetailDecorator(Details detail) { + this.detail = detail; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java new file mode 100644 index 000000000..5108c8f50 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; + +import java.util.Map; + +public interface Details { + Map getExtendedDetails(Map statusMap, Item item); +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java new file mode 100644 index 000000000..e813574f5 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java @@ -0,0 +1,22 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; +import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; + +import java.util.HashMap; +import java.util.Map; + +public class PersistentVolumeClaimDetails extends DetailDecorator { + public PersistentVolumeClaimDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, Item item) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); + var persistentVolumeClaim = (PersistentVolumeClaim) item.getWrappedItem(); + mewDetailMap.put("phase status", persistentVolumeClaim.getStatus().getPhase()); + mewDetailMap.put("storage class", persistentVolumeClaim.getSpec().getStorageClassName()); + return mewDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java new file mode 100644 index 000000000..ed8057f66 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java @@ -0,0 +1,29 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; +import io.fabric8.kubernetes.api.model.PersistentVolume; + +import java.util.HashMap; +import java.util.Map; + +public class PersistentVolumeDetails extends DetailDecorator { + public PersistentVolumeDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, Item item) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); + var persistentVolume = (PersistentVolume) item.getWrappedItem(); + newDetailMap.put("phase status", persistentVolume.getStatus().getPhase()); + newDetailMap.put("storage class", persistentVolume.getSpec().getStorageClassName()); + newDetailMap.put("reclaim policy", persistentVolume.getSpec().getPersistentVolumeReclaimPolicy()); + var accessMode = new StringBuilder(); + for (String entity : persistentVolume.getSpec().getAccessModes()) { + accessMode.append(entity).append("\n"); + } + newDetailMap.put("storage mode", accessMode.toString()); + persistentVolume.getSpec().getCapacity().forEach((key, value) -> newDetailMap.put(key, value.getAmount() + value.getFormat())); + return newDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java new file mode 100644 index 000000000..ef3bd3f8e --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java @@ -0,0 +1,23 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.items.Item; +import io.fabric8.kubernetes.api.model.Service; + +import java.util.HashMap; +import java.util.Map; + +public class ServiceDetails extends DetailDecorator { + public ServiceDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, Item item) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); + var service = (Service) item.getWrappedItem(); + mewDetailMap.put("cluster ip", service.getSpec().getClusterIP()); + mewDetailMap.put("service type", service.getSpec().getType()); + mewDetailMap.put("session affinity", service.getSpec().getSessionAffinity()); + return mewDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java new file mode 100644 index 000000000..c40914c47 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java @@ -0,0 +1,38 @@ +package de.bonndan.nivio.input.kubernetes.items; + + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.DeploymentDetails; +import de.bonndan.nivio.input.kubernetes.status.BoolStatus; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class DeploymentItem implements Item { + private final Deployment deployment; + + public DeploymentItem(Deployment deployment) { + this.deployment = deployment; + } + + @NonNull + public HasMetadata getWrappedItem() { + return deployment; + } + + public static List getDeploymentItems(@NonNull KubernetesClient client) { + var deploymentList = client.apps().deployments().list().getItems(); + return deploymentList.stream().map(deployment -> { + var deploymentItem = new K8sItemBuilder(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new DeploymentItem(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); + deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); + return deploymentItem; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java new file mode 100644 index 000000000..f99f65b2e --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java @@ -0,0 +1,7 @@ +package de.bonndan.nivio.input.kubernetes.items; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +public interface Item { + HasMetadata getWrappedItem(); +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java similarity index 55% rename from src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java index a13ea98d2..8fa269ac8 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PersistentVolumeClaimItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java @@ -1,14 +1,16 @@ -package de.bonndan.nivio.input.kubernetes; +package de.bonndan.nivio.input.kubernetes.items; import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeClaimDetails; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class PersistentVolumeClaimItem implements Item { @@ -23,21 +25,8 @@ public HasMetadata getWrappedItem() { return persistentVolumeClaim; } - @Override - public Map getStatus(Map status) { - return null; - } - - @Override - public Map getDetails() { - var details = new HashMap(); - details.put("phase status", persistentVolumeClaim.getStatus().getPhase()); - details.put("storage class", persistentVolumeClaim.getSpec().getStorageClassName()); - return details; - } - public static List getPersistentVolumeClaimItems(KubernetesClient client) { var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItem(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeClaimItem(persistentVolumeClaims))).collect(Collectors.toList()); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeClaimItem(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java new file mode 100644 index 000000000..78703d104 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java @@ -0,0 +1,34 @@ +package de.bonndan.nivio.input.kubernetes.items; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeDetails; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class PersistentVolumeItem implements Item { + private final PersistentVolume persistentVolume; + + public PersistentVolumeItem(PersistentVolume persistentVolume) { + this.persistentVolume = persistentVolume; + } + + + @NonNull + public HasMetadata getWrappedItem() { + return persistentVolume; + } + + + public static List getPersistentVolumeItems(KubernetesClient client) { + var getPersistentVolumeList = client.persistentVolumes().list().getItems(); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeItem(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java similarity index 50% rename from src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java index 1c6b4fdab..6231955e2 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java @@ -1,15 +1,15 @@ -package de.bonndan.nivio.input.kubernetes; +package de.bonndan.nivio.input.kubernetes.items; -import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.status.BoolStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; import java.util.List; -import java.util.Locale; -import java.util.Map; import java.util.stream.Collectors; public class PodItem implements Item { @@ -25,28 +25,10 @@ public HasMetadata getWrappedItem() { } - @NonNull - public Map getStatus(Map status) { - return status.entrySet().stream().collect(Collectors.toMap( - pair -> "condition." + pair.getKey().toLowerCase(), - pair -> { - if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { - return Status.GREEN.toString(); - } else { - return Status.RED.toString(); - } - })); - } - - @Override - public Map getDetails() { - return null; - } - public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new K8sItem(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new PodItem(pod)); + var podItem = new K8sItemBuilder(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new PodItem(pod)).addStatus(new BoolStatus()).build(); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java new file mode 100644 index 000000000..d128ce14f --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java @@ -0,0 +1,38 @@ +package de.bonndan.nivio.input.kubernetes.items; + + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.ReplicaSet; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class ReplicaSetItem implements Item { + private final ReplicaSet replicaSet; + + public ReplicaSetItem(ReplicaSet replicaSet) { + this.replicaSet = replicaSet; + } + + @NonNull + @Override + public HasMetadata getWrappedItem() { + return replicaSet; + } + + + public static List getReplicaSetItems(KubernetesClient client) { + var replicaSetList = client.apps().replicaSets().list().getItems(); + return replicaSetList.stream().map(replicaSet -> { + var replicaSetItem = new K8sItemBuilder(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new ReplicaSetItem(replicaSet)).addStatus(new ReplicaStatus()).build(); + replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); + return replicaSetItem; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java new file mode 100644 index 000000000..5f44680db --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java @@ -0,0 +1,33 @@ +package de.bonndan.nivio.input.kubernetes.items; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.ServiceDetails; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class ServiceItem implements Item { + private final Service service; + + public ServiceItem(Service service) { + this.service = service; + } + + @NonNull + public HasMetadata getWrappedItem() { + return service; + } + + + public static List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> new K8sItemBuilder(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new ServiceItem(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java similarity index 65% rename from src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java index aa3f2688f..f3ea86ed7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/StatefulSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java @@ -1,13 +1,15 @@ -package de.bonndan.nivio.input.kubernetes; +package de.bonndan.nivio.input.kubernetes.items; import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.StatefulSet; import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class StatefulSetItem implements Item { @@ -23,18 +25,8 @@ public HasMetadata getWrappedItem() { return statefulSet; } - @Override - public Map getStatus(Map status) { - return null; - } - - @Override - public Map getDetails() { - return null; - } - public static List getStatefulSetItems(KubernetesClient client) { var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new K8sItem(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new StatefulSetItem(statefulSet))).collect(Collectors.toList()); + return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new StatefulSetItem(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java new file mode 100644 index 000000000..b903c6e1d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -0,0 +1,22 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.items.Item; + +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; + +public class BoolStatus implements Status { + @Override + public Map getExtendedStatus(Map statusMap, Item item) { + return statusMap.entrySet().stream().collect(Collectors.toMap( + pair -> "condition." + pair.getKey().toLowerCase(), + pair -> { + if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { + return de.bonndan.nivio.assessment.Status.GREEN.toString(); + } else { + return de.bonndan.nivio.assessment.Status.RED.toString(); + } + })); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java new file mode 100644 index 000000000..8fc915e33 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java @@ -0,0 +1,13 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.items.Item; + +import java.util.HashMap; +import java.util.Map; + +public class DefaultStatus implements Status { + @Override + public Map getExtendedStatus(Map statusMap, Item item) { + return new HashMap<>(); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java new file mode 100644 index 000000000..f4c08cffd --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -0,0 +1,40 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.items.Item; +import io.fabric8.kubernetes.api.model.apps.ReplicaSet; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; + +public class ReplicaStatus implements Status { + + @Override + public Map getExtendedStatus(Map statusMap, Item item) { + Integer replicaCount; + Integer replicaCountDesired; + if (item.getWrappedItem() instanceof ReplicaSet) { + var concreteItem = (ReplicaSet) item.getWrappedItem(); + replicaCount = concreteItem.getStatus().getReadyReplicas(); + replicaCountDesired = concreteItem.getSpec().getReplicas(); + } else if (item.getWrappedItem() instanceof StatefulSet) { + var concreteItem = (StatefulSet) item.getWrappedItem(); + replicaCount = concreteItem.getStatus().getReadyReplicas(); + replicaCountDesired = concreteItem.getSpec().getReplicas(); + } else { + return statusMap; + } + var message = String.format("condition.%s of %s Pods are ready", replicaCount, replicaCountDesired); + if (replicaCount == null) { + return Collections.singletonMap("condition.ReadyReplicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } else if (replicaCountDesired == null) { + return Collections.singletonMap("condition.Replicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } else if (Objects.equals(replicaCount, replicaCountDesired)) { + return Collections.singletonMap("condition.all pods are ready", de.bonndan.nivio.assessment.Status.GREEN.toString()); + } else if (replicaCount == 0) { + return Collections.singletonMap(message, de.bonndan.nivio.assessment.Status.RED.toString()); + } else + return Collections.singletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java new file mode 100644 index 000000000..e18aad6b6 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.items.Item; + +import java.util.Map; + +public interface Status { + Map getExtendedStatus(Map statusMap, Item item); +} From 35d73942cbea98653cae72ceda6e07d426624933 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 19 Jul 2021 09:58:09 +0200 Subject: [PATCH 098/310] [#139] bumped spring version --- pom.xml | 31 ++++++++++++------- .../bonndan/nivio/input/KubernetesTest.java | 3 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 318c4a52c..734f2875b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 2.2.13.RELEASE + 2.5.2 jar @@ -19,12 +19,13 @@ 1.11 11 5.4.0 - 2.24.0 + 3.11.2 + 0.20.1 0.8.6 ${project.basedir}/src/main/app v12.18.2 v1.22.4 - 1.10.0 + 1.12.0 8.8.2 dedica-team_nivio dedica-team @@ -71,44 +72,52 @@ org.springframework.boot spring-boot-starter-test test - + + + org.junit + junit + + + org.mockito + mockito-core + - com.vaadin.external.google - android-json + org.mockito + mockito-all org.junit.jupiter junit-jupiter-api - 5.4.0 + ${junit-jupiter.version} test org.junit.jupiter junit-jupiter-engine - 5.4.0 + ${junit-jupiter.version} test org.mockito mockito-junit-jupiter - 2.25.0 + ${mockito.version} test com.tngtech.archunit archunit-junit5 - 0.19.0 + ${archunit.version} test com.tngtech.archunit archunit - 0.14.1 + ${archunit.version} test diff --git a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/KubernetesTest.java index 5f0aa2ef9..6a99eb04c 100644 --- a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/KubernetesTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -21,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@EnableKubernetesMockClient(crud = true) +@EnableKubernetesMockClient(crud = true, https = false) public class KubernetesTest { static KubernetesClient client; From d8e167686ccce79e12be6df563664b20e3ebbb73 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 19 Jul 2021 10:39:45 +0200 Subject: [PATCH 099/310] [#139] bumped openapi generator version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 734f2875b..8149050c8 100644 --- a/pom.xml +++ b/pom.xml @@ -270,7 +270,7 @@ org.openapitools openapi-generator - 5.1.0 + 5.1.1 From a201510ec74f9a1a028d62d34c3596c89f5f71b8 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 13:53:33 +0200 Subject: [PATCH 100/310] add the new attribute demo and the set/get methods --- src/main/java/de/bonndan/nivio/config/SeedProperties.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index 6089848a3..19abe76bc 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -2,10 +2,13 @@ import org.springframework.boot.context.properties.ConfigurationProperties; +import java.util.Optional; + @ConfigurationProperties(prefix = "nivio") public class SeedProperties { private String seed; + private String demo; // add this attribute for the environment variable DEMO public String getSeed() { return seed; @@ -14,4 +17,8 @@ public String getSeed() { public void setSeed(String seed) { this.seed = seed; } + + public String getDemo(){return demo;} + + public void setDemo(String demo){this.demo = demo;} } From 2898f997c59fff9ae25d7461feeba5e1b83f8811 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 13:54:55 +0200 Subject: [PATCH 101/310] add the new attribute seedProperties, define a new constructor and modify the getDemoFiles() method --- src/main/java/de/bonndan/nivio/input/Seed.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index f992ee8f2..1690095b3 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -66,10 +66,10 @@ private URL asURL(String s) { */ public List getDemoFiles() { List demoFiles = new ArrayList<>(); - if (seedProperties.getSeed().isEmpty()) { + if (StringUtils.isEmpty(seedProperties.getDemo())) { return demoFiles; } - String value = seedProperties.getSeed(); + String value = seedProperties.getDemo(); Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); From ceb1419eccb7a1cd3c76374ce55baba4e17f96a0 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 13:56:17 +0200 Subject: [PATCH 102/310] add the new attribute seedProperties, define a new constructor and modify the method trigger() --- src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java index a881bd645..030f73e50 100644 --- a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java +++ b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java @@ -10,6 +10,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import java.io.File; import java.nio.file.Paths; @@ -36,7 +37,7 @@ public ChangeTrigger(LandscapeDescriptionFactory landscapeDescriptionFactory, @Scheduled(initialDelay = 20000, fixedDelay = 30000) public void trigger() { - if (seedProperties.getSeed().isEmpty()) { + if (StringUtils.isEmpty(seedProperties.getDemo())) { LOGGER.debug("DEMO not set, not simulating any pet clinic events."); return; } From 1a7135b4457fb32ec1b58589417f90498de5a68d Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 13:57:38 +0200 Subject: [PATCH 103/310] modify the bean seed() --- src/main/java/de/bonndan/nivio/config/ApplicationConfig.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index 1ef36c493..f86363dab 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -41,8 +41,7 @@ public RestTemplate restTemplate() { @Bean public Seed seed() { - - return new Seed(Optional.ofNullable(seedProperties.getSeed()),seedProperties); + return new Seed(Optional.ofNullable(seedProperties.getDemo()), seedProperties); } @Bean From bf63be5a92fc12591edba48c62dd3ba55c501221 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 13:59:09 +0200 Subject: [PATCH 104/310] add the new attribute seedProperties, define a new constructor and modify the method onApplicationEvent() --- src/main/java/de/bonndan/nivio/input/StartupListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/StartupListener.java b/src/main/java/de/bonndan/nivio/input/StartupListener.java index 0c8a14075..47cc9af6d 100644 --- a/src/main/java/de/bonndan/nivio/input/StartupListener.java +++ b/src/main/java/de/bonndan/nivio/input/StartupListener.java @@ -42,7 +42,7 @@ public StartupListener(LandscapeDescriptionFactory landscapeDescriptionFactory, @Override public void onApplicationEvent(final ApplicationReadyEvent event) { - if (!StringUtils.isEmpty(seedProperties.getSeed().isEmpty())) { + if (!StringUtils.isEmpty(seedProperties.getDemo())) { LOGGER.info("Running in demo mode"); } From 5e2157e9ce6296c579489ea30c1953f64165325b Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 14:12:29 +0200 Subject: [PATCH 105/310] modify the metods setup() and fires() --- .../java/de/bonndan/nivio/input/StartupListenerTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java index f1b96c6ad..d8d8112f2 100644 --- a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java +++ b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java @@ -26,20 +26,20 @@ class StartupListenerTest { private SeedProperties seedProperties; private Seed seed = new Seed(Optional.empty(), null); // will use Seed.NIVIO_ENV_DIRECTORY - + @BeforeEach public void setup() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - startupListener = new StartupListener(factory, publisher, seed,seedProperties); + seedProperties = mock(SeedProperties.class); + startupListener = new StartupListener(factory, publisher, seed, null); } @Test public void fires() throws MalformedURLException { - //given seed = new Seed(Optional.of("https://dedica.team"),null); - startupListener = new StartupListener(factory, publisher, seed,seedProperties); + startupListener = new StartupListener(factory, publisher, seed, null); LandscapeDescription landscapeDescription = new LandscapeDescription("foo", "bar", null); landscapeDescription.setSource(new LandscapeSource(new URL("https://dedica.team"))); From 8066df764691616195400f7ab5d09d88cec28d35 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 15:35:43 +0200 Subject: [PATCH 106/310] modify the constructor StartupListener --- .../java/de/bonndan/nivio/input/StartupListener.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/StartupListener.java b/src/main/java/de/bonndan/nivio/input/StartupListener.java index 47cc9af6d..2f5f57887 100644 --- a/src/main/java/de/bonndan/nivio/input/StartupListener.java +++ b/src/main/java/de/bonndan/nivio/input/StartupListener.java @@ -15,6 +15,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -30,14 +31,16 @@ public class StartupListener implements ApplicationListener Date: Mon, 19 Jul 2021 16:32:53 +0200 Subject: [PATCH 107/310] Add Adapter Structure --- docs/source/schema/Models/ItemDescription.rst | 4 +- docs/source/schema/spec.json | 4 +- .../InputFormatHandlerKubernetes.java | 56 +++++----- .../nivio/input/kubernetes/K8sItem.java | 31 +++--- .../input/kubernetes/K8sItemBuilder.java | 17 +-- .../nivio/input/kubernetes/K8sJsonParser.java | 6 +- .../kubernetes/details/DefaultDetails.java | 16 ++- .../kubernetes/details/DeploymentDetails.java | 19 +++- .../input/kubernetes/details/Details.java | 4 +- .../details/PersistentVolumeClaimDetails.java | 23 ++-- .../details/PersistentVolumeDetails.java | 35 +++--- .../kubernetes/details/ServiceDetails.java | 26 +++-- .../DeploymentItemAdapter.java} | 32 +++++- .../kubernetes/itemadapters/ItemAdapter.java | 16 +++ .../PersistentVolumeClaimItemAdapter.java | 60 ++++++++++ .../PersistentVolumeItemAdapter.java | 75 +++++++++++++ .../PodItemAdapter.java} | 27 ++++- .../ReplicaSetItemAdapter.java} | 36 +++++- .../itemadapters/ServiceItemAdapter.java | 64 +++++++++++ .../itemadapters/StatefulSetItemAdapter.java | 60 ++++++++++ .../nivio/input/kubernetes/items/Item.java | 7 -- .../items/PersistentVolumeClaimItem.java | 32 ------ .../items/PersistentVolumeItem.java | 34 ------ .../input/kubernetes/items/ServiceItem.java | 33 ------ .../kubernetes/items/StatefulSetItem.java | 32 ------ .../input/kubernetes/status/BoolStatus.java | 4 +- .../kubernetes/status/DefaultStatus.java | 13 --- .../kubernetes/status/ReplicaStatus.java | 24 ++-- .../nivio/input/kubernetes/status/Status.java | 4 +- .../input/kubernetes/DeploymentItemTest.java | 105 ------------------ 30 files changed, 513 insertions(+), 386 deletions(-) rename src/main/java/de/bonndan/nivio/input/kubernetes/{items/DeploymentItem.java => itemadapters/DeploymentItemAdapter.java} (60%) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java rename src/main/java/de/bonndan/nivio/input/kubernetes/{items/PodItem.java => itemadapters/PodItemAdapter.java} (58%) rename src/main/java/de/bonndan/nivio/input/kubernetes/{items/ReplicaSetItem.java => itemadapters/ReplicaSetItemAdapter.java} (54%) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java delete mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 022f72838..18a1c4582 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -83,12 +83,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The lifecycle state of an item. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 176e56577..c2a4636e2 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -213,7 +213,7 @@ "EOL" ] }, - "statuses": { + "status": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -226,7 +226,7 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "status": { + "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index ee70ab497..d11594b1f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -22,13 +22,13 @@ import java.util.*; import java.util.stream.Collectors; -import static de.bonndan.nivio.input.kubernetes.items.DeploymentItem.getDeploymentItems; -import static de.bonndan.nivio.input.kubernetes.items.PersistentVolumeClaimItem.getPersistentVolumeClaimItems; -import static de.bonndan.nivio.input.kubernetes.items.PersistentVolumeItem.getPersistentVolumeItems; -import static de.bonndan.nivio.input.kubernetes.items.PodItem.getPodItems; -import static de.bonndan.nivio.input.kubernetes.items.ReplicaSetItem.getReplicaSetItems; -import static de.bonndan.nivio.input.kubernetes.items.ServiceItem.getServiceItems; -import static de.bonndan.nivio.input.kubernetes.items.StatefulSetItem.getStatefulSetItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter.getDeploymentItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter.getPersistentVolumeClaimItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter.getPersistentVolumeItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter.getPodItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter.getReplicaSetItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter.getServiceItems; +import static de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter.getStatefulSetItems; /** * Scans the k8s api for services, pods, volumes etc. @@ -118,45 +118,45 @@ private List createItemDescription(List itemList) { }).collect(Collectors.toList()); } - private void crossReferenceLabel(ArrayList items) { - items.forEach(item -> { - var ownerList = items.stream().filter( - item1 -> CollectionUtils.intersection(Objects.requireNonNullElse(item.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), - Objects.requireNonNullElse(item1.getItemContainer().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) - .size() >= 2 && item1.getLevelDecorator().getLevel() != -1 && item.getLevelDecorator().getLevel() != -1 && - (item1.getLevelDecorator().getLevel() - item.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); - ownerList.forEach(item::addOwner); + private void crossReferenceLabel(ArrayList itemList) { + itemList.forEach(ownedItem -> { + var ownerList = itemList.stream().filter( + ownerItem -> CollectionUtils.intersection(Objects.requireNonNullElse(ownedItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), + Objects.requireNonNullElse(ownerItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) + .size() >= 2 && ownerItem.getLevelDecorator().getLevel() != -1 && ownedItem.getLevelDecorator().getLevel() != -1 && + (ownerItem.getLevelDecorator().getLevel() - ownedItem.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); + ownerList.forEach(ownedItem::addOwner); }); } private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { - persistentVolumeClaimList.forEach(item -> { + persistentVolumeClaimList.forEach(persistentVolume -> { var owners = new ArrayList(); - owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemContainer().getWrappedItem()).getSpec().getVolumes().stream().filter(volume -> volume.getPersistentVolumeClaim() != null).map(volumeNonNull -> volumeNonNull.getPersistentVolumeClaim().getClaimName()).collect(Collectors.toList()).contains(item.getName())) + owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemAdapter().getWrappedItem()).getSpec().getVolumes().stream().filter(volume -> volume.getPersistentVolumeClaim() != null).map(volumeNonNull -> volumeNonNull.getPersistentVolumeClaim().getClaimName()).collect(Collectors.toList()).contains(persistentVolume.getName())) .collect(Collectors.toList()); - owners.forEach(item::addOwner); + owners.forEach(persistentVolume::addOwner); }); } - private void crossReferenceOwner(ArrayList items) { - items.forEach(item -> { + private void crossReferenceOwner(ArrayList itemList) { + itemList.forEach(ownedItem -> { var owners = new ArrayList(); - owners = (ArrayList) items.stream().filter(item1 -> item.getItemContainer().getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(item1.getUid())).collect(Collectors.toList()); - owners.forEach(item::addOwner); + owners = (ArrayList) itemList.stream().filter(ownerItem -> ownedItem.getItemAdapter().getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(ownerItem.getUid())).collect(Collectors.toList()); + owners.forEach(ownedItem::addOwner); }); } private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { - persistentVolumes.forEach(item -> { - var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) item.getItemContainer().getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); - claimer.forEach(item::addOwner); + persistentVolumes.forEach(ownedItem -> { + var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) ownedItem.getItemAdapter().getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); + claimer.forEach(ownedItem::addOwner); }); } private void crossReferenceService(List service, List owners) { - service.forEach(item -> { - var claimer = owners.stream().filter(claimItem -> (item.getName().equals(claimItem.getName()))).collect(Collectors.toList()); - claimer.forEach(item::addOwner); + service.forEach(ownedItem -> { + var claimer = owners.stream().filter(claimItem -> (ownedItem.getName().equals(claimItem.getName()))).collect(Collectors.toList()); + claimer.forEach(ownedItem::addOwner); }); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index f5093d134..0afb24d83 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -2,7 +2,7 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.kubernetes.details.Details; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import de.bonndan.nivio.input.kubernetes.status.Status; import org.springframework.lang.NonNull; @@ -14,21 +14,17 @@ public class K8sItem { private final List owners = new ArrayList<>(); private final LevelDecorator levelDecorator; - private final Item itemContainer; + private final ItemAdapter itemAdapter; private final Details details; private final Status status; - private final String name; private final String type; - private final String uid; - public K8sItem(String name, String uid, String type, Item itemContainer, Status status, Details details) { - this.levelDecorator = new LevelDecorator(K8sJsonParser.getExperimentalLevel(itemContainer.getClass())); - this.itemContainer = itemContainer; + public K8sItem(String type, ItemAdapter itemAdapter, Status status, Details details) { + this.levelDecorator = new LevelDecorator(K8sJsonParser.getExperimentalLevel(itemAdapter.getClass())); + this.itemAdapter = itemAdapter; this.details = details; this.status = status; - this.name = name; this.type = type; - this.uid = uid; } public void addOwner(@NonNull K8sItem owner) { @@ -46,7 +42,7 @@ public void addStatus(@NonNull String key, @NonNull String value) { @NonNull public String getGroup() { if (this.getOwner().isEmpty()) { - return name; + return itemAdapter.getName(); } else { return this.getOwner().get(0).getGroup(); } @@ -58,7 +54,7 @@ public LevelDecorator getLevelDecorator() { @NonNull public String getName() { - return name; + return itemAdapter.getName(); } @NonNull @@ -73,8 +69,11 @@ public List getRelationDescriptionList() { @NonNull public Map getDetails() { - var newLabelMap = new HashMap<>(status.getExtendedStatus(labelMap, itemContainer)); - var test = details.getExtendedDetails(labelMap, itemContainer); + var newLabelMap = new HashMap(); + if (status != null) { + newLabelMap.putAll(status.getExtendedStatus(labelMap, itemAdapter)); + } + var test = details.getExtendedDetails(labelMap, itemAdapter); newLabelMap.putAll(test); return newLabelMap; } @@ -86,12 +85,12 @@ public String getType() { @NonNull public String getUid() { - return uid; + return itemAdapter.getUid(); } @NonNull - public Item getItemContainer() { - return itemContainer; + public ItemAdapter getItemAdapter() { + return itemAdapter; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java index 460a5a901..488bf44e3 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java @@ -2,25 +2,20 @@ import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; import de.bonndan.nivio.input.kubernetes.details.Details; -import de.bonndan.nivio.input.kubernetes.items.Item; -import de.bonndan.nivio.input.kubernetes.status.DefaultStatus; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import de.bonndan.nivio.input.kubernetes.status.Status; public class K8sItemBuilder { - private final String name; private final String type; - private final String uid; - private final Item item; + private final ItemAdapter itemAdapter; private Details details; private Status status; - public K8sItemBuilder(String name, String uid, String type, Item item) { + public K8sItemBuilder(String type, ItemAdapter itemAdapter) { this.details = new DefaultDetails(); - this.status = new DefaultStatus(); - this.item = item; - this.name = name; + this.itemAdapter = itemAdapter; + this.status = null; this.type = type; - this.uid = uid; } public K8sItemBuilder addStatus(Status status) { @@ -34,6 +29,6 @@ public K8sItemBuilder addDetails(Details details) { } public K8sItem build() { - return new K8sItem(name, uid, type, item, status, details); + return new K8sItem(type, itemAdapter, status, details); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java index 94e6e0c9e..fda2b37f8 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -1,6 +1,6 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.slf4j.Logger; @@ -26,12 +26,12 @@ public static boolean getExperimentalActive() { var companyList = (JSONObject) jsonObject.get("experimentalFeatureLabel"); active = Boolean.parseBoolean(companyList.get("active").toString()); } catch (Exception e) { - e.printStackTrace(); + LOGGER.warn(e.getMessage()); } return active; } - public static int getExperimentalLevel(Class classToParse) { + public static int getExperimentalLevel(Class classToParse) { var objectName = classToParse.getSimpleName(); if (cacheMap.containsKey(objectName)) { return cacheMap.get(objectName); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java index a7c6ded8a..3505fe12b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java @@ -1,17 +1,23 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public class DefaultDetails implements Details { + + @NonNull @Override - public Map getExtendedDetails(Map statusMap, Item item) { + public Map getExtendedDetails(@Nullable Map statusMap, @NonNull ItemAdapter itemAdapter) { + Objects.requireNonNull(itemAdapter); var labels = new HashMap(); - labels.putIfAbsent("name", item.getWrappedItem().getMetadata().getName()); - labels.putIfAbsent("namespace", item.getWrappedItem().getMetadata().getNamespace()); - labels.putIfAbsent("creation", item.getWrappedItem().getMetadata().getCreationTimestamp()); + labels.putIfAbsent("name", itemAdapter.getName()); + labels.putIfAbsent("namespace", itemAdapter.getNamespace()); + labels.putIfAbsent("creation", itemAdapter.getCreationTimestamp()); return labels; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java index f77e207be..753238efe 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java @@ -1,20 +1,29 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; -import io.fabric8.kubernetes.api.model.apps.Deployment; +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class DeploymentDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentDetails.class); + public DeploymentDetails(Details detail) { super(detail); } @Override - public Map getExtendedDetails(Map statusMap, Item item) { - var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); - newDetailMap.put("strategy", ((Deployment) item.getWrappedItem()).getSpec().getStrategy().getType()); + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + newDetailMap.put("strategy", ((DeploymentItemAdapter) itemAdapter).getStrategyType()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } return newDetailMap; } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java index 5108c8f50..78d30ef52 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java @@ -1,9 +1,9 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import java.util.Map; public interface Details { - Map getExtendedDetails(Map statusMap, Item item); + Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java index e813574f5..013f73f0a 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java @@ -1,22 +1,31 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; -import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class PersistentVolumeClaimDetails extends DetailDecorator { + + private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeClaimDetails.class); + public PersistentVolumeClaimDetails(Details detail) { super(detail); } @Override - public Map getExtendedDetails(Map statusMap, Item item) { - var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); - var persistentVolumeClaim = (PersistentVolumeClaim) item.getWrappedItem(); - mewDetailMap.put("phase status", persistentVolumeClaim.getStatus().getPhase()); - mewDetailMap.put("storage class", persistentVolumeClaim.getSpec().getStorageClassName()); + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + var persistentVolumeClaim = (PersistentVolumeClaimItemAdapter) itemAdapter; + mewDetailMap.put("phase status", persistentVolumeClaim.getPhase()); + mewDetailMap.put("storage class", persistentVolumeClaim.getStorageClassName()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } return mewDetailMap; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java index ed8057f66..b8c2a9be1 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java @@ -1,29 +1,38 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; -import io.fabric8.kubernetes.api.model.PersistentVolume; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class PersistentVolumeDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeDetails.class); + public PersistentVolumeDetails(Details detail) { super(detail); } @Override - public Map getExtendedDetails(Map statusMap, Item item) { - var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); - var persistentVolume = (PersistentVolume) item.getWrappedItem(); - newDetailMap.put("phase status", persistentVolume.getStatus().getPhase()); - newDetailMap.put("storage class", persistentVolume.getSpec().getStorageClassName()); - newDetailMap.put("reclaim policy", persistentVolume.getSpec().getPersistentVolumeReclaimPolicy()); - var accessMode = new StringBuilder(); - for (String entity : persistentVolume.getSpec().getAccessModes()) { - accessMode.append(entity).append("\n"); + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + var persistentVolume = (PersistentVolumeItemAdapter) itemAdapter; + newDetailMap.put("phase status", persistentVolume.getPhase()); + newDetailMap.put("storage class", persistentVolume.getStorageClassName()); + newDetailMap.put("reclaim policy", persistentVolume.getPersistentVolumeReclaimPolicy()); + var accessMode = new StringBuilder(); + for (String entity : persistentVolume.getAccessModes()) { + accessMode.append(entity).append("\n"); + } + newDetailMap.put("storage mode", accessMode.toString()); + persistentVolume.getCapacity().forEach((key, value) -> newDetailMap.put(key, value.getAmount() + value.getFormat())); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); } - newDetailMap.put("storage mode", accessMode.toString()); - persistentVolume.getSpec().getCapacity().forEach((key, value) -> newDetailMap.put(key, value.getAmount() + value.getFormat())); + return newDetailMap; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java index ef3bd3f8e..742ab84d8 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java @@ -1,23 +1,33 @@ package de.bonndan.nivio.input.kubernetes.details; -import de.bonndan.nivio.input.kubernetes.items.Item; -import io.fabric8.kubernetes.api.model.Service; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class ServiceDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceDetails.class); + + public ServiceDetails(Details detail) { super(detail); } @Override - public Map getExtendedDetails(Map statusMap, Item item) { - var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, item)); - var service = (Service) item.getWrappedItem(); - mewDetailMap.put("cluster ip", service.getSpec().getClusterIP()); - mewDetailMap.put("service type", service.getSpec().getType()); - mewDetailMap.put("session affinity", service.getSpec().getSessionAffinity()); + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + + try { + var service = (ServiceItemAdapter) itemAdapter; + mewDetailMap.put("cluster ip", service.getClusterIP()); + mewDetailMap.put("service type", service.getType()); + mewDetailMap.put("session affinity", service.getSessionAffinity()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } return mewDetailMap; } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java similarity index 60% rename from src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java index c40914c47..4e7f8dc39 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/DeploymentItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java @@ -1,4 +1,4 @@ -package de.bonndan.nivio.input.kubernetes.items; +package de.bonndan.nivio.input.kubernetes.itemadapters; import de.bonndan.nivio.input.ItemType; @@ -15,10 +15,10 @@ import java.util.List; import java.util.stream.Collectors; -public class DeploymentItem implements Item { +public class DeploymentItemAdapter implements ItemAdapter { private final Deployment deployment; - public DeploymentItem(Deployment deployment) { + public DeploymentItemAdapter(Deployment deployment) { this.deployment = deployment; } @@ -27,10 +27,34 @@ public HasMetadata getWrappedItem() { return deployment; } + @Override + public String getUid() { + return deployment.getMetadata().getUid(); + } + + @Override + public String getName() { + return deployment.getMetadata().getName(); + } + + @Override + public String getNamespace() { + return deployment.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return deployment.getMetadata().getCreationTimestamp(); + } + + public String getStrategyType() { + return deployment.getSpec().getStrategy().getType(); + } + public static List getDeploymentItems(@NonNull KubernetesClient client) { var deploymentList = client.apps().deployments().list().getItems(); return deploymentList.stream().map(deployment -> { - var deploymentItem = new K8sItemBuilder(deployment.getMetadata().getName(), deployment.getMetadata().getUid(), ItemType.DEPLOYMENT, new DeploymentItem(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); + var deploymentItem = new K8sItemBuilder(ItemType.DEPLOYMENT, new DeploymentItemAdapter(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); return deploymentItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java new file mode 100644 index 000000000..2f2dceeba --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java @@ -0,0 +1,16 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +public interface ItemAdapter { + + HasMetadata getWrappedItem(); + + String getUid(); + + String getName(); + + String getNamespace(); + + String getCreationTimestamp(); +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java new file mode 100644 index 000000000..f00f50f0a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java @@ -0,0 +1,60 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeClaimDetails; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class PersistentVolumeClaimItemAdapter implements ItemAdapter { + private final PersistentVolumeClaim persistentVolumeClaim; + + public PersistentVolumeClaimItemAdapter(PersistentVolumeClaim persistentVolumeClaim) { + this.persistentVolumeClaim = persistentVolumeClaim; + } + + @NonNull + public HasMetadata getWrappedItem() { + return persistentVolumeClaim; + } + + @Override + public String getName() { + return persistentVolumeClaim.getMetadata().getName(); + } + + @Override + public String getUid() { + return persistentVolumeClaim.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return persistentVolumeClaim.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return persistentVolumeClaim.getMetadata().getCreationTimestamp(); + } + + public String getPhase() { + return persistentVolumeClaim.getStatus().getPhase(); + } + + public String getStorageClassName() { + return persistentVolumeClaim.getSpec().getStorageClassName(); + } + + public static List getPersistentVolumeClaimItems(KubernetesClient client) { + var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeClaimItemAdapter(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java new file mode 100644 index 000000000..d1cb9c0f2 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java @@ -0,0 +1,75 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeDetails; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.api.model.Quantity; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PersistentVolumeItemAdapter implements ItemAdapter { + private final PersistentVolume persistentVolume; + + public PersistentVolumeItemAdapter(PersistentVolume persistentVolume) { + this.persistentVolume = persistentVolume; + } + + + @NonNull + public HasMetadata getWrappedItem() { + return persistentVolume; + } + + @Override + public String getName() { + return persistentVolume.getMetadata().getName(); + } + + @Override + public String getUid() { + return persistentVolume.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return persistentVolume.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return persistentVolume.getMetadata().getCreationTimestamp(); + } + + public String getPhase() { + return persistentVolume.getStatus().getPhase(); + } + + public String getStorageClassName() { + return persistentVolume.getSpec().getStorageClassName(); + } + + public String getPersistentVolumeReclaimPolicy() { + return persistentVolume.getSpec().getPersistentVolumeReclaimPolicy(); + } + + public List getAccessModes() { + return persistentVolume.getSpec().getAccessModes(); + } + + public Map getCapacity() { + return persistentVolume.getSpec().getCapacity(); + } + + public static List getPersistentVolumeItems(KubernetesClient client) { + var getPersistentVolumeList = client.persistentVolumes().list().getItems(); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeItemAdapter(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java similarity index 58% rename from src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java index 6231955e2..4f3d11583 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PodItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java @@ -1,4 +1,4 @@ -package de.bonndan.nivio.input.kubernetes.items; +package de.bonndan.nivio.input.kubernetes.itemadapters; import de.bonndan.nivio.input.ItemType; import de.bonndan.nivio.input.kubernetes.K8sItem; @@ -12,10 +12,10 @@ import java.util.List; import java.util.stream.Collectors; -public class PodItem implements Item { +public class PodItemAdapter implements ItemAdapter { private final Pod pod; - public PodItem(Pod pod) { + public PodItemAdapter(Pod pod) { this.pod = pod; } @@ -24,11 +24,30 @@ public HasMetadata getWrappedItem() { return pod; } + @Override + public String getName() { + return pod.getMetadata().getName(); + } + + @Override + public String getUid() { + return pod.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return pod.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return pod.getMetadata().getCreationTimestamp(); + } public static List getPodItems(KubernetesClient client) { var pods = client.pods().list().getItems(); return pods.stream().map(pod -> { - var podItem = new K8sItemBuilder(pod.getMetadata().getName(), pod.getMetadata().getUid(), ItemType.POD, new PodItem(pod)).addStatus(new BoolStatus()).build(); + var podItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(pod)).addStatus(new BoolStatus()).build(); pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); return podItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java similarity index 54% rename from src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java rename to src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java index d128ce14f..0a4853662 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ReplicaSetItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java @@ -1,4 +1,4 @@ -package de.bonndan.nivio.input.kubernetes.items; +package de.bonndan.nivio.input.kubernetes.itemadapters; import de.bonndan.nivio.input.ItemType; @@ -13,10 +13,10 @@ import java.util.List; import java.util.stream.Collectors; -public class ReplicaSetItem implements Item { +public class ReplicaSetItemAdapter implements ItemAdapter { private final ReplicaSet replicaSet; - public ReplicaSetItem(ReplicaSet replicaSet) { + public ReplicaSetItemAdapter(ReplicaSet replicaSet) { this.replicaSet = replicaSet; } @@ -26,11 +26,39 @@ public HasMetadata getWrappedItem() { return replicaSet; } + @Override + public String getName() { + return replicaSet.getMetadata().getName(); + } + + @Override + public String getUid() { + return replicaSet.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return replicaSet.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return replicaSet.getMetadata().getCreationTimestamp(); + } + + public Integer getReadyReplicas() { + return replicaSet.getStatus().getReadyReplicas(); + } + + public Integer getReplicas() { + return replicaSet.getSpec().getReplicas(); + } + public static List getReplicaSetItems(KubernetesClient client) { var replicaSetList = client.apps().replicaSets().list().getItems(); return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new K8sItemBuilder(replicaSet.getMetadata().getName(), replicaSet.getMetadata().getUid(), ItemType.REPLICASET, new ReplicaSetItem(replicaSet)).addStatus(new ReplicaStatus()).build(); + var replicaSetItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(replicaSet)).addStatus(new ReplicaStatus()).build(); replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); return replicaSetItem; }).collect(Collectors.toList()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java new file mode 100644 index 000000000..d1eb45faf --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java @@ -0,0 +1,64 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.ServiceDetails; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class ServiceItemAdapter implements ItemAdapter { + private final Service service; + + public ServiceItemAdapter(Service service) { + this.service = service; + } + + @NonNull + public HasMetadata getWrappedItem() { + return service; + } + + @Override + public String getName() { + return service.getMetadata().getName(); + } + + @Override + public String getUid() { + return service.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return service.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return service.getMetadata().getCreationTimestamp(); + } + + public String getClusterIP() { + return service.getSpec().getClusterIP(); + } + + public String getType() { + return service.getSpec().getType(); + } + + public String getSessionAffinity() { + return service.getSpec().getSessionAffinity(); + } + + public static List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> new K8sItemBuilder(ItemType.SERVICE, new ServiceItemAdapter(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java new file mode 100644 index 000000000..cf4de9dc7 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java @@ -0,0 +1,60 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.K8sItem; +import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; +import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class StatefulSetItemAdapter implements ItemAdapter { + private final StatefulSet statefulSet; + + public StatefulSetItemAdapter(StatefulSet statefulSet) { + this.statefulSet = statefulSet; + } + + @Override + @NonNull + public HasMetadata getWrappedItem() { + return statefulSet; + } + + @Override + public String getName() { + return statefulSet.getMetadata().getName(); + } + + @Override + public String getUid() { + return statefulSet.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return statefulSet.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return statefulSet.getMetadata().getCreationTimestamp(); + } + + public Integer getReadyReplicas() { + return statefulSet.getStatus().getReadyReplicas(); + } + + public Integer getReplicas() { + return statefulSet.getSpec().getReplicas(); + } + + public static List getStatefulSetItems(KubernetesClient client) { + var statefulSetList = client.apps().statefulSets().list().getItems(); + return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(ItemType.STATEFULSET, new StatefulSetItemAdapter(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java deleted file mode 100644 index f99f65b2e..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/Item.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.items; - -import io.fabric8.kubernetes.api.model.HasMetadata; - -public interface Item { - HasMetadata getWrappedItem(); -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java deleted file mode 100644 index 8fa269ac8..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeClaimItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.items; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeClaimDetails; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.stream.Collectors; - -public class PersistentVolumeClaimItem implements Item { - private final PersistentVolumeClaim persistentVolumeClaim; - - public PersistentVolumeClaimItem(PersistentVolumeClaim persistentVolumeClaim) { - this.persistentVolumeClaim = persistentVolumeClaim; - } - - @NonNull - public HasMetadata getWrappedItem() { - return persistentVolumeClaim; - } - - public static List getPersistentVolumeClaimItems(KubernetesClient client) { - var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(persistentVolumeClaims.getMetadata().getName(), persistentVolumeClaims.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeClaimItem(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java deleted file mode 100644 index 78703d104..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/PersistentVolumeItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.items; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeDetails; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.PersistentVolume; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.stream.Collectors; - -public class PersistentVolumeItem implements Item { - private final PersistentVolume persistentVolume; - - public PersistentVolumeItem(PersistentVolume persistentVolume) { - this.persistentVolume = persistentVolume; - } - - - @NonNull - public HasMetadata getWrappedItem() { - return persistentVolume; - } - - - public static List getPersistentVolumeItems(KubernetesClient client) { - var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(persistentVolume.getMetadata().getName(), persistentVolume.getMetadata().getUid(), ItemType.VOLUME, new PersistentVolumeItem(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java deleted file mode 100644 index 5f44680db..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/ServiceItem.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.items; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.ServiceDetails; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.stream.Collectors; - -public class ServiceItem implements Item { - private final Service service; - - public ServiceItem(Service service) { - this.service = service; - } - - @NonNull - public HasMetadata getWrappedItem() { - return service; - } - - - public static List getServiceItems(KubernetesClient client) { - var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new K8sItemBuilder(service.getMetadata().getName(), service.getMetadata().getUid(), ItemType.SERVICE, new ServiceItem(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java deleted file mode 100644 index f3ea86ed7..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/items/StatefulSetItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.items; - -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.apps.StatefulSet; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.springframework.lang.NonNull; - -import java.util.List; -import java.util.stream.Collectors; - -public class StatefulSetItem implements Item { - private final StatefulSet statefulSet; - - public StatefulSetItem(StatefulSet statefulSet) { - this.statefulSet = statefulSet; - } - - @Override - @NonNull - public HasMetadata getWrappedItem() { - return statefulSet; - } - - public static List getStatefulSetItems(KubernetesClient client) { - var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(statefulSet.getMetadata().getName(), statefulSet.getMetadata().getUid(), ItemType.STATEFULSET, new StatefulSetItem(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java index b903c6e1d..d4015a6dc 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -1,6 +1,6 @@ package de.bonndan.nivio.input.kubernetes.status; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import java.util.Locale; import java.util.Map; @@ -8,7 +8,7 @@ public class BoolStatus implements Status { @Override - public Map getExtendedStatus(Map statusMap, Item item) { + public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { return statusMap.entrySet().stream().collect(Collectors.toMap( pair -> "condition." + pair.getKey().toLowerCase(), pair -> { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java deleted file mode 100644 index 8fc915e33..000000000 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/DefaultStatus.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.bonndan.nivio.input.kubernetes.status; - -import de.bonndan.nivio.input.kubernetes.items.Item; - -import java.util.HashMap; -import java.util.Map; - -public class DefaultStatus implements Status { - @Override - public Map getExtendedStatus(Map statusMap, Item item) { - return new HashMap<>(); - } -} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java index f4c08cffd..27b4c9b9f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -1,8 +1,8 @@ package de.bonndan.nivio.input.kubernetes.status; -import de.bonndan.nivio.input.kubernetes.items.Item; -import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; import java.util.Collections; import java.util.Map; @@ -11,17 +11,17 @@ public class ReplicaStatus implements Status { @Override - public Map getExtendedStatus(Map statusMap, Item item) { + public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { Integer replicaCount; Integer replicaCountDesired; - if (item.getWrappedItem() instanceof ReplicaSet) { - var concreteItem = (ReplicaSet) item.getWrappedItem(); - replicaCount = concreteItem.getStatus().getReadyReplicas(); - replicaCountDesired = concreteItem.getSpec().getReplicas(); - } else if (item.getWrappedItem() instanceof StatefulSet) { - var concreteItem = (StatefulSet) item.getWrappedItem(); - replicaCount = concreteItem.getStatus().getReadyReplicas(); - replicaCountDesired = concreteItem.getSpec().getReplicas(); + if (itemAdapter instanceof ReplicaSetItemAdapter) { + var concreteItem = (ReplicaSetItemAdapter) itemAdapter; + replicaCount = concreteItem.getReadyReplicas(); + replicaCountDesired = concreteItem.getReplicas(); + } else if (itemAdapter instanceof StatefulSetItemAdapter) { + var concreteItem = (StatefulSetItemAdapter) itemAdapter; + replicaCount = concreteItem.getReadyReplicas(); + replicaCountDesired = concreteItem.getReplicas(); } else { return statusMap; } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java index e18aad6b6..8acf3ce6f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java @@ -1,9 +1,9 @@ package de.bonndan.nivio.input.kubernetes.status; -import de.bonndan.nivio.input.kubernetes.items.Item; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import java.util.Map; public interface Status { - Map getExtendedStatus(Map statusMap, Item item); + Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter); } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java deleted file mode 100644 index 20b439419..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/DeploymentItemTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -/* -@EnableKubernetesMockClient(crud = true, https = false) -class DeploymentItemTest { - Deployment deployment; - DeploymentItem deploymentItem; - KubernetesClient kubernetesClient; - - @BeforeEach - void setUp() { - deployment = new DeploymentBuilder() - .withNewMetadata() - .withName("test") - .withNamespace("test") - .withUid("1234") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec(new DeploymentSpecBuilder() - .build()) - .withStatus(new DeploymentStatusBuilder() - .build()) - .build(); - kubernetesClient.apps().deployments().create(deployment); - - deploymentItem = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, deployment, new LevelDecorator(4)); - } - - @Test - void testGetWrappedItem() { - HasMetadata result = deploymentItem.getWrappedItem(); - assertThat(result).isEqualTo(deployment); - } - - @Test - void testGetDeploymentItems() { - List result = DeploymentItem.getDeploymentItems(kubernetesClient); - assertThat(result.size()).isEqualTo(Collections.singletonList(new DeploymentItem("test", "1234", ItemType.VOLUME, deployment, new LevelDecorator(4))).size()); - result.forEach(item -> assertThat(item).isEqualToComparingFieldByField(deploymentItem)); - } - - @Test - void testAddOwner() { - var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); - deploymentItem.addOwner(owner); - assertThat(deploymentItem.getOwner()).isEqualTo(Collections.singletonList(owner)); - } - - @Test - void testAddOwnerNull() { - assertThatThrownBy(() -> deploymentItem.addOwner(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddRelation() { - var relation = new RelationDescription("source", "target"); - deploymentItem.addRelation(relation); - assertThat(deploymentItem.getRelationDescriptionList()).isEqualTo(Collections.singletonList(relation)); - } - - @Test - void testAddRelationNull() { - assertThatThrownBy(() -> deploymentItem.addRelation(null)).isInstanceOf(NullPointerException.class); - } - - @Test - void testAddStatusGreen() { - deploymentItem.addStatus("key", "true"); - assertThat(deploymentItem.getStatus()).isEqualTo(Collections.singletonMap("key", "green")); - } - - @Test - void testAddStatusRed() { - deploymentItem.addStatus("key", "false"); - assertThat(deploymentItem.getStatus()).isEqualTo(Collections.singletonMap("key", "red")); - } - - @Test - void testAddStatusNull() { - assertThatThrownBy(() -> deploymentItem.addStatus(null, null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> deploymentItem.addStatus("null", null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> deploymentItem.addStatus(null, "null")).isInstanceOf(NullPointerException.class); - } - - @Test - void testGetGroup() { - var owner = new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4)); - deploymentItem.addOwner(owner); - String result = deploymentItem.getGroup(); - assertThat(result).isEqualTo("test"); - } - - @Test - void testSetOwners() { - List owner = Collections.singletonList(new DeploymentItem("test", "1234", ItemType.DEPLOYMENT, null, new LevelDecorator(4))); - deploymentItem.setOwners(owner); - assertThat(deploymentItem.getOwner()).isEqualTo(owner); - } - - @Test - void testSetOwnersNull() { - assertThatThrownBy(() -> deploymentItem.setOwners(null)).isInstanceOf(NullPointerException.class); - } -} -*/ From fae56366e1d1529513180e610b0d716f1ce0ff80 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 19 Jul 2021 16:37:21 +0200 Subject: [PATCH 108/310] Add Tests --- .../details/DefaultDetailsTest.java | 32 ++++++++++++ .../details/DeploymentDetailsTest.java | 46 +++++++++++++++++ .../PersistentVolumeClaimDetailsTest.java | 51 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java new file mode 100644 index 000000000..e22e01fe8 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java @@ -0,0 +1,32 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DefaultDetailsTest { + DefaultDetails defaultDetails = new DefaultDetails(); + + @Test + void testGetExtendedDetails() { + ItemAdapter itemAdapter = Mockito.mock(ItemAdapter.class); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Map result = defaultDetails.getExtendedDetails(new HashMap<>() {{ + put("String", "String"); + }}, itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "creation", "creationTimestamp")); + } + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> defaultDetails.getExtendedDetails(null, null)); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java new file mode 100644 index 000000000..b0da92694 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java @@ -0,0 +1,46 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DeploymentDetailsTest { + DeploymentDetails deploymentDetails; + DeploymentItemAdapter itemAdapter; + + @BeforeEach + void setUp() { + itemAdapter = Mockito.mock(DeploymentItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getStrategyType()).thenReturn("strategyType"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + } + + @Test + void testGetExtendedDetails() { + deploymentDetails = new DeploymentDetails(new DefaultDetails()); + Map result = deploymentDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + } + + @Test + void testGetExtendedDetailsClassCastException() { + ServiceDetails serviceDetails = new ServiceDetails(new DeploymentDetails(new DefaultDetails())); + Map result = serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + } + + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> deploymentDetails.getExtendedDetails(null, null)); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java new file mode 100644 index 000000000..3f0719f57 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java @@ -0,0 +1,51 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import io.fabric8.kubernetes.api.model.Quantity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PersistentVolumeClaimDetailsTest { + + PersistentVolumeDetails persistentVolumeDetails; + PersistentVolumeItemAdapter itemAdapter; + + @BeforeEach + void setUp() { + itemAdapter = Mockito.mock(PersistentVolumeItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getAccessModes()).thenReturn(List.of("testMode")); + Mockito.when(itemAdapter.getPhase()).thenReturn("phase"); + Mockito.when(itemAdapter.getPersistentVolumeReclaimPolicy()).thenReturn("persistentVolumeReclaimPolicy"); + Mockito.when(itemAdapter.getCapacity()).thenReturn(Map.of("testCapacity", new Quantity("8", "gi"))); + } + + @Test + void testGetExtendedDetails() { + persistentVolumeDetails = new PersistentVolumeDetails(new DefaultDetails()); + Map result = persistentVolumeDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + } + + @Test + void testGetExtendedDetailsClassCastException() { + ServiceDetails serviceDetails = new ServiceDetails(new PersistentVolumeDetails(new DefaultDetails())); + Map result = serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + } + + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> persistentVolumeDetails.getExtendedDetails(null, null)); + } +} From 5865dce7e65c204274da3e7e314277b20b77121c Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 16:39:25 +0200 Subject: [PATCH 109/310] add a constructor --- src/main/java/de/bonndan/nivio/config/SeedProperties.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index 19abe76bc..662ebb82d 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -21,4 +21,11 @@ public void setSeed(String seed) { public String getDemo(){return demo;} public void setDemo(String demo){this.demo = demo;} + + public SeedProperties(String seed, String demo) + { + this.seed = seed; + this.demo = demo; + } + } From fb1a6588bca2bee4dedf73b221fc03ec1a11e4b2 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 16:43:19 +0200 Subject: [PATCH 110/310] define the variable seedProperties and modify the variable seed and modify the methods setup() and fires() --- .../de/bonndan/nivio/input/StartupListenerTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java index d8d8112f2..ce5dd6e08 100644 --- a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java +++ b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java @@ -23,8 +23,8 @@ class StartupListenerTest { private LandscapeDescriptionFactory factory; private ApplicationEventPublisher publisher; private StartupListener startupListener; - private SeedProperties seedProperties; - private Seed seed = new Seed(Optional.empty(), null); // will use Seed.NIVIO_ENV_DIRECTORY + private SeedProperties seedProperties = new SeedProperties("src/test/resources/example/inout.yml","1"); + private Seed seed = new Seed(Optional.empty(), seedProperties); // will use Seed.NIVIO_ENV_DIRECTORY @BeforeEach @@ -32,14 +32,14 @@ public void setup() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); seedProperties = mock(SeedProperties.class); - startupListener = new StartupListener(factory, publisher, seed, null); + startupListener = new StartupListener(factory, publisher, seed, seedProperties); } @Test public void fires() throws MalformedURLException { //given - seed = new Seed(Optional.of("https://dedica.team"),null); - startupListener = new StartupListener(factory, publisher, seed, null); + seed = new Seed(Optional.of("https://dedica.team"),seedProperties); + startupListener = new StartupListener(factory, publisher, seed,seedProperties); LandscapeDescription landscapeDescription = new LandscapeDescription("foo", "bar", null); landscapeDescription.setSource(new LandscapeSource(new URL("https://dedica.team"))); From bc4c6be55bc244bf3ab3acde25010e08ceb43200 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 19 Jul 2021 17:00:41 +0200 Subject: [PATCH 111/310] Merge develop into feature branch Add tests --- docs/source/schema/.openapi-generator/VERSION | 2 +- docs/source/schema/Models/ItemDescription.rst | 4 ++-- docs/source/schema/Models/LandscapeDescription.rst | 10 +++++----- docs/source/schema/spec.json | 12 ++++++------ .../nivio/assessment/kpi/KubernetesKPI.java | 14 ++++++++++++-- .../details/PersistentVolumeDetails.java | 2 +- .../details/PersistentVolumeClaimDetailsTest.java | 5 +++-- 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/docs/source/schema/.openapi-generator/VERSION b/docs/source/schema/.openapi-generator/VERSION index acf69b48b..3bff05917 100644 --- a/docs/source/schema/.openapi-generator/VERSION +++ b/docs/source/schema/.openapi-generator/VERSION @@ -1 +1 @@ -5.1.0 \ No newline at end of file +5.1.1 \ No newline at end of file diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..022f72838 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -83,12 +83,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The lifecycle state of an item. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..dd41a02f8 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -73,16 +73,16 @@ LandscapeDescription - - optional, defaults to null - null - * - items - - List - - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - - optional, defaults to null - - null * - partial - Boolean - marks that the landscape is not complete, but an update - optional, defaults to null - null + * - items + - List + - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. + - optional, defaults to null + - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index c2a4636e2..a73231647 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -213,7 +213,7 @@ "EOL" ] }, - "status": { + "statuses": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -226,7 +226,7 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "statuses": { + "status": { "type": "array", "description": "A list of statuses that works like hardcoded KPIs.", "writeOnly": true, @@ -423,6 +423,10 @@ "icon": { "type": "string" }, + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" + }, "items": { "type": "array", "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", @@ -431,10 +435,6 @@ "$ref": "#/components/schemas/ItemDescription" } }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" - }, "links": { "type": "object", "additionalProperties": { diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index 22dd06908..a0a7e126e 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -6,7 +6,7 @@ import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; import org.springframework.lang.NonNull; -import org.springframework.util.StringUtils; +import org.springframework.util.ObjectUtils; import java.util.ArrayList; import java.util.List; @@ -28,7 +28,7 @@ public List getStatusValues(Component component) { for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { String key = entry.getKey(); String flag = entry.getValue(); - if (StringUtils.isEmpty(flag)) + if (ObjectUtils.isEmpty(flag)) continue; if (key.startsWith("condition.")) { var message = key.replaceFirst("condition.", ""); @@ -48,4 +48,14 @@ public String getDescription() { public boolean isEnabled() { return true; } + + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return null; + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java index b8c2a9be1..5f6365e3c 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java @@ -25,7 +25,7 @@ public Map getExtendedDetails(Map statusMap, Ite newDetailMap.put("reclaim policy", persistentVolume.getPersistentVolumeReclaimPolicy()); var accessMode = new StringBuilder(); for (String entity : persistentVolume.getAccessModes()) { - accessMode.append(entity).append("\n"); + accessMode.append(entity); } newDetailMap.put("storage mode", accessMode.toString()); persistentVolume.getCapacity().forEach((key, value) -> newDetailMap.put(key, value.getAmount() + value.getFormat())); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java index 3f0719f57..d164adbe7 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java @@ -27,20 +27,21 @@ void setUp() { Mockito.when(itemAdapter.getPhase()).thenReturn("phase"); Mockito.when(itemAdapter.getPersistentVolumeReclaimPolicy()).thenReturn("persistentVolumeReclaimPolicy"); Mockito.when(itemAdapter.getCapacity()).thenReturn(Map.of("testCapacity", new Quantity("8", "gi"))); + Mockito.when(itemAdapter.getStorageClassName()).thenReturn("testStorage"); } @Test void testGetExtendedDetails() { persistentVolumeDetails = new PersistentVolumeDetails(new DefaultDetails()); Map result = persistentVolumeDetails.getExtendedDetails(Map.of(), itemAdapter); - assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + assertThat(result).isEqualTo(Map.of("creation", "creationTimestamp", "name", "name", "namespace", "namespace", "phase status", "phase", "reclaim policy", "persistentVolumeReclaimPolicy", "storage class", "testStorage", "storage mode", "testMode", "testCapacity", "8gi")); } @Test void testGetExtendedDetailsClassCastException() { ServiceDetails serviceDetails = new ServiceDetails(new PersistentVolumeDetails(new DefaultDetails())); Map result = serviceDetails.getExtendedDetails(Map.of(), itemAdapter); - assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + assertThat(result).isEqualTo(Map.of("creation", "creationTimestamp", "name", "name", "namespace", "namespace", "phase status", "phase", "reclaim policy", "persistentVolumeReclaimPolicy", "storage class", "testStorage", "storage mode", "testMode", "testCapacity", "8gi")); } From 4225e4b6be6d9658386a62fa962cf527adbfb455 Mon Sep 17 00:00:00 2001 From: BriceNtchoumou Date: Mon, 19 Jul 2021 19:20:59 +0200 Subject: [PATCH 112/310] use the @ConstructorBinding Annotation --- .../java/de/bonndan/nivio/config/SeedProperties.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java index 662ebb82d..6d4d209e6 100644 --- a/src/main/java/de/bonndan/nivio/config/SeedProperties.java +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -1,10 +1,10 @@ package de.bonndan.nivio.config; import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.Optional; +import org.springframework.boot.context.properties.ConstructorBinding; @ConfigurationProperties(prefix = "nivio") +@ConstructorBinding public class SeedProperties { private String seed; @@ -14,14 +14,8 @@ public String getSeed() { return seed; } - public void setSeed(String seed) { - this.seed = seed; - } - public String getDemo(){return demo;} - public void setDemo(String demo){this.demo = demo;} - public SeedProperties(String seed, String demo) { this.seed = seed; From 1143456f4c837340aae54f6bda6d6db546a887b8 Mon Sep 17 00:00:00 2001 From: robert Date: Tue, 20 Jul 2021 17:58:52 +0200 Subject: [PATCH 113/310] Move status logic to KPI Add JavaDoc Move K8sItem factory logic to different class --- docs/source/inc_labels.rst | 1 + .../schema/Models/LandscapeDescription.rst | 10 +-- docs/source/schema/spec.json | 8 +-- src/main/app/src/labels.json | 23 ++++++- .../nivio/assessment/kpi/KubernetesKPI.java | 53 +++++++++++---- .../nivio/input/kubernetes/CreateItems.java | 64 +++++++++++++++++++ .../InputFormatHandlerKubernetes.java | 26 +++++--- .../nivio/input/kubernetes/K8sItem.java | 5 ++ .../nivio/input/kubernetes/K8sJsonParser.java | 30 +++++++-- .../itemadapters/DeploymentItemAdapter.java | 19 +----- .../PersistentVolumeClaimItemAdapter.java | 14 +--- .../PersistentVolumeItemAdapter.java | 12 +--- .../itemadapters/PodItemAdapter.java | 17 +---- .../itemadapters/ReplicaSetItemAdapter.java | 16 ----- .../itemadapters/ServiceItemAdapter.java | 14 +--- .../itemadapters/StatefulSetItemAdapter.java | 13 +--- .../input/kubernetes/status/BoolStatus.java | 11 +--- .../kubernetes/status/ReplicaStatus.java | 21 +----- .../java/de/bonndan/nivio/model/Item.java | 3 +- .../java/de/bonndan/nivio/model/Label.java | 4 +- .../{app => resources}/k8sLabelConfig.json | 1 + ....java => PersistentVolumeDetailsTest.java} | 6 +- 22 files changed, 202 insertions(+), 169 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java rename src/main/{app => resources}/k8sLabelConfig.json (84%) rename src/test/java/de/bonndan/nivio/input/kubernetes/details/{PersistentVolumeClaimDetailsTest.java => PersistentVolumeDetailsTest.java} (89%) diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index a501de5da..58bf07f39 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -5,6 +5,7 @@ * ``frameworks`` A comma-separated list of frameworks as key-value pairs (key is name, value is version). * ``health`` Description of the item's health status. * ``icon`` Icon/image (for displaying purposes). +* ``k8s`` Prefix for k8s labels. * ``layer`` A technical layer. * ``lifecycle`` A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``). * ``note`` A custom note. diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index dd41a02f8..807ed451f 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,6 +63,11 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null * - color - String - @@ -73,11 +78,6 @@ LandscapeDescription - - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - items - List - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index a73231647..800e22315 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -417,16 +417,16 @@ }, "description": "Additional labels for the landscape." }, + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" + }, "color": { "type": "string" }, "icon": { "type": "string" }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" - }, "items": { "type": "array", "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index a38b4beab..635b98963 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -1 +1,22 @@ -{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items."} \ No newline at end of file +{ + "capability": "The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.", + "color": "A hex color code to override the inherited group color", + "costs": "Running costs of the item.", + "fill": "Background image (for displaying purposes).", + "frameworks": "A comma-separated list of frameworks as key-value pairs (key is name, value is version).", + "health": "Description of the item's health status.", + "icon": "Icon/image (for displaying purposes).", + "k8s": "Prefix for k8s labels.", + "layer": "A technical layer.", + "lifecycle": "A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).", + "note": "A custom note.", + "scale": "Number of instances.", + "security": "Description of the item's security status.", + "shortname": "Abbreviated name.", + "software": "Software/OS name.", + "stability": "Description of the item's stability.", + "team": "Name of the responsible team (e.g. technical owner).", + "type": "The type (service, database, queue, load balancer, etc.).", + "version": "The version (e.g. software version or protocol version).", + "visibility": "Visibility to other items." +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index a0a7e126e..15145a3b7 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -5,12 +5,12 @@ import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import org.apache.commons.collections.map.SingletonMap; import org.springframework.lang.NonNull; import org.springframework.util.ObjectUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; public class KubernetesKPI implements KPI { public static final String IDENTIFIER = "k8s"; @@ -24,21 +24,48 @@ public List getStatusValues(Component component) { var statusList = new ArrayList(); - var id = 1; - for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { - String key = entry.getKey(); - String flag = entry.getValue(); - if (ObjectUtils.isEmpty(flag)) - continue; - if (key.startsWith("condition.")) { - var message = key.replaceFirst("condition.", ""); - statusList.add(new StatusValue(IDENTIFIER + ":" + id++, Status.from(flag), message)); + var counter = new AtomicInteger(0); + ((Labeled) component).getLabels(Label.k8s).forEach((key, value) -> { + if (!ObjectUtils.isEmpty(value)) { + var message = key.replaceFirst("k8s.", ""); + if (message.startsWith("boolcondition.")) { + message = message.replaceFirst("boolcondition.", ""); + statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message)); + } else if (message.startsWith("replicacondition.")) { + var splitValue = value.split(";"); + var replicaCondition = replicaCondition(Integer.parseInt(splitValue[0]), Integer.parseInt(splitValue[1])); + statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(String.valueOf(replicaCondition.getValue())), String.valueOf(replicaCondition.getKey()))); + } else { + statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(value), message)); + } } - } + }); return statusList; } + private String boolCondition(String flag) { + if (flag.toLowerCase(Locale.ROOT).equals("true")) { + return de.bonndan.nivio.assessment.Status.GREEN.toString(); + } else { + return de.bonndan.nivio.assessment.Status.RED.toString(); + } + } + + private SingletonMap replicaCondition(Integer replicaCount, Integer replicaCountDesired) { + var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); + if (replicaCount == null) { + return new SingletonMap("ReadyReplicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } else if (replicaCountDesired == null) { + return new SingletonMap("Replicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } else if (Objects.equals(replicaCount, replicaCountDesired)) { + return new SingletonMap("all pods are ready", de.bonndan.nivio.assessment.Status.GREEN.toString()); + } else if (replicaCount == 0) { + return new SingletonMap(message, de.bonndan.nivio.assessment.Status.RED.toString()); + } else + return new SingletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); + } + @Override public String getDescription() { return "Evaluates Kubernetes conditions"; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java b/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java new file mode 100644 index 000000000..8c2b0c19a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java @@ -0,0 +1,64 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.details.*; +import de.bonndan.nivio.input.kubernetes.itemadapters.*; +import de.bonndan.nivio.input.kubernetes.status.BoolStatus; +import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class CreateItems { + private CreateItems() { + } + + public static List getDeploymentItems(@NonNull KubernetesClient client) { + var deploymentList = client.apps().deployments().list().getItems(); + return deploymentList.stream().map(deployment -> { + var deploymentItem = new K8sItemBuilder(ItemType.DEPLOYMENT, new DeploymentItemAdapter(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); + deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); + return deploymentItem; + }).collect(Collectors.toList()); + } + + public static List getPersistentVolumeClaimItems(KubernetesClient client) { + var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeClaimItemAdapter(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getPersistentVolumeItems(KubernetesClient client) { + var getPersistentVolumeList = client.persistentVolumes().list().getItems(); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeItemAdapter(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getPodItems(KubernetesClient client) { + var pods = client.pods().list().getItems(); + return pods.stream().map(pod -> { + var podItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(pod)).addStatus(new BoolStatus()).build(); + pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); + return podItem; + }).collect(Collectors.toList()); + } + + public static List getReplicaSetItems(KubernetesClient client) { + var replicaSetList = client.apps().replicaSets().list().getItems(); + return replicaSetList.stream().map(replicaSet -> { + var replicaSetItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(replicaSet)).addStatus(new ReplicaStatus()).build(); + replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); + return replicaSetItem; + }).collect(Collectors.toList()); + } + + public static List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> new K8sItemBuilder(ItemType.SERVICE, new ServiceItemAdapter(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getStatefulSetItems(KubernetesClient client) { + var statefulSetList = client.apps().statefulSets().list().getItems(); + return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(ItemType.STATEFULSET, new StatefulSetItemAdapter(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index d11594b1f..d40b4e3fe 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -22,13 +22,7 @@ import java.util.*; import java.util.stream.Collectors; -import static de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter.getDeploymentItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter.getPersistentVolumeClaimItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter.getPersistentVolumeItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter.getPodItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter.getReplicaSetItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter.getServiceItems; -import static de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter.getStatefulSetItems; +import static de.bonndan.nivio.input.kubernetes.CreateItems.*; /** * Scans the k8s api for services, pods, volumes etc. @@ -69,6 +63,13 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } } + /** + * This method collects all Kubernetes objects encapsulated in K8sItems and creates ItemDescription from them + * + * @param client the KubernetesClient is used to get the K8s Objects + * @return a list of ItemDescriptions + */ + private List getItemDescription(KubernetesClient client) { var persistentVolumeClaims = getPersistentVolumeClaimItems(client); var persistentVolumes = getPersistentVolumeItems(client); @@ -118,12 +119,18 @@ private List createItemDescription(List itemList) { }).collect(Collectors.toList()); } + /** + * The crossReferenceLevel Method tries to match K8sItems via their Label. It is restricted via the level of a K8sItem and a minimal of matching labels. + * + * @param itemList all K8sItems + */ + private void crossReferenceLabel(ArrayList itemList) { itemList.forEach(ownedItem -> { var ownerList = itemList.stream().filter( ownerItem -> CollectionUtils.intersection(Objects.requireNonNullElse(ownedItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), Objects.requireNonNullElse(ownerItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) - .size() >= 2 && ownerItem.getLevelDecorator().getLevel() != -1 && ownedItem.getLevelDecorator().getLevel() != -1 && + .size() >= K8sJsonParser.getMinMatchingLevel() && ownerItem.getLevelDecorator().getLevel() != -1 && ownedItem.getLevelDecorator().getLevel() != -1 && (ownerItem.getLevelDecorator().getLevel() - ownedItem.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); ownerList.forEach(ownedItem::addOwner); }); @@ -132,8 +139,7 @@ private void crossReferenceLabel(ArrayList itemList) { private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { persistentVolumeClaimList.forEach(persistentVolume -> { var owners = new ArrayList(); - owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemAdapter().getWrappedItem()).getSpec().getVolumes().stream().filter(volume -> volume.getPersistentVolumeClaim() != null).map(volumeNonNull -> volumeNonNull.getPersistentVolumeClaim().getClaimName()).collect(Collectors.toList()).contains(persistentVolume.getName())) - .collect(Collectors.toList()); + owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemAdapter().getWrappedItem()).getSpec().getVolumes().stream().anyMatch(volume -> volume.getPersistentVolumeClaim() != null && volume.getPersistentVolumeClaim().getClaimName().equals(persistentVolume.getName()))).collect(Collectors.toList()); owners.forEach(persistentVolume::addOwner); }); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index 0afb24d83..d07a55871 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -8,6 +8,11 @@ import java.util.*; +/** + * The K8sItem Class is intended to unify the K8s Objects up to an certain point and to store relation data between those. + */ + + public class K8sItem { private final List relationDescriptionList = new ArrayList<>(); private final Map labelMap = new HashMap<>(); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java index fda2b37f8..0c707efba 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -5,14 +5,22 @@ import org.json.simple.parser.JSONParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; import java.io.FileReader; import java.util.HashMap; +/** + * Parses config values for the crossReferenceLabel feature + */ + +@Service public class K8sJsonParser { private static final Logger LOGGER = LoggerFactory.getLogger(K8sJsonParser.class); private static final HashMap cacheMap = new HashMap<>(); + private static final String JSONLABEL = "experimentalFeatureLabel"; + private static final String FILEPATH = "src/main/resources/k8sLabelConfig.json"; private K8sJsonParser() { } @@ -21,9 +29,9 @@ public static boolean getExperimentalActive() { var parser = new JSONParser(); var active = false; try { - var obj = parser.parse(new FileReader("src/main/app/k8sLabelConfig.json")); + var obj = parser.parse(new FileReader(FILEPATH)); var jsonObject = (JSONObject) obj; - var companyList = (JSONObject) jsonObject.get("experimentalFeatureLabel"); + var companyList = (JSONObject) jsonObject.get(JSONLABEL); active = Boolean.parseBoolean(companyList.get("active").toString()); } catch (Exception e) { LOGGER.warn(e.getMessage()); @@ -31,6 +39,20 @@ public static boolean getExperimentalActive() { return active; } + public static int getMinMatchingLevel() { + var parser = new JSONParser(); + var minMatchingLabels = 4; + try { + var obj = parser.parse(new FileReader(FILEPATH)); + var jsonObject = (JSONObject) obj; + var companyList = (JSONObject) jsonObject.get(JSONLABEL); + minMatchingLabels = Integer.parseInt(companyList.get("min_matching_label").toString()); + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + return minMatchingLabels; + } + public static int getExperimentalLevel(Class classToParse) { var objectName = classToParse.getSimpleName(); if (cacheMap.containsKey(objectName)) { @@ -43,9 +65,9 @@ public static int getExperimentalLevel(Class classToParse private static int getExperimentalLevelFromJSON(String objectName) { var parser = new JSONParser(); try { - var obj = parser.parse(new FileReader("src/main/app/k8sLabelConfig.json")); + var obj = parser.parse(new FileReader(FILEPATH)); var jsonObject = (JSONObject) obj; - var experimentalFeature = (JSONObject) jsonObject.get("experimentalFeatureLabel"); + var experimentalFeature = (JSONObject) jsonObject.get(JSONLABEL); var level = (JSONObject) experimentalFeature.get("level"); var classLevel = level.get(objectName); var finalLevel = Integer.parseInt(String.valueOf(classLevel)); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java index 4e7f8dc39..d6115ee2b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java @@ -1,20 +1,10 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.DeploymentDetails; -import de.bonndan.nivio.input.kubernetes.status.BoolStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class DeploymentItemAdapter implements ItemAdapter { private final Deployment deployment; @@ -51,12 +41,5 @@ public String getStrategyType() { return deployment.getSpec().getStrategy().getType(); } - public static List getDeploymentItems(@NonNull KubernetesClient client) { - var deploymentList = client.apps().deployments().list().getItems(); - return deploymentList.stream().map(deployment -> { - var deploymentItem = new K8sItemBuilder(ItemType.DEPLOYMENT, new DeploymentItemAdapter(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); - deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); - return deploymentItem; - }).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java index f00f50f0a..58671e8b3 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java @@ -1,18 +1,9 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeClaimDetails; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class PersistentVolumeClaimItemAdapter implements ItemAdapter { private final PersistentVolumeClaim persistentVolumeClaim; @@ -53,8 +44,5 @@ public String getStorageClassName() { return persistentVolumeClaim.getSpec().getStorageClassName(); } - public static List getPersistentVolumeClaimItems(KubernetesClient client) { - var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); - return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeClaimItemAdapter(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java index d1cb9c0f2..b00f700f7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java @@ -1,19 +1,12 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.PersistentVolumeDetails; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.PersistentVolume; import io.fabric8.kubernetes.api.model.Quantity; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; public class PersistentVolumeItemAdapter implements ItemAdapter { private final PersistentVolume persistentVolume; @@ -68,8 +61,5 @@ public Map getCapacity() { return persistentVolume.getSpec().getCapacity(); } - public static List getPersistentVolumeItems(KubernetesClient client) { - var getPersistentVolumeList = client.persistentVolumes().list().getItems(); - return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeItemAdapter(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java index 4f3d11583..6b7fb1353 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java @@ -1,17 +1,9 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.status.BoolStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class PodItemAdapter implements ItemAdapter { private final Pod pod; @@ -44,12 +36,5 @@ public String getCreationTimestamp() { return pod.getMetadata().getCreationTimestamp(); } - public static List getPodItems(KubernetesClient client) { - var pods = client.pods().list().getItems(); - return pods.stream().map(pod -> { - var podItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(pod)).addStatus(new BoolStatus()).build(); - pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); - return podItem; - }).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java index 0a4853662..992221535 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java @@ -1,18 +1,10 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class ReplicaSetItemAdapter implements ItemAdapter { private final ReplicaSet replicaSet; @@ -55,12 +47,4 @@ public Integer getReplicas() { } - public static List getReplicaSetItems(KubernetesClient client) { - var replicaSetList = client.apps().replicaSets().list().getItems(); - return replicaSetList.stream().map(replicaSet -> { - var replicaSetItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(replicaSet)).addStatus(new ReplicaStatus()).build(); - replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); - return replicaSetItem; - }).collect(Collectors.toList()); - } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java index d1eb45faf..2b40b87b1 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java @@ -1,18 +1,9 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; -import de.bonndan.nivio.input.kubernetes.details.ServiceDetails; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class ServiceItemAdapter implements ItemAdapter { private final Service service; @@ -57,8 +48,5 @@ public String getSessionAffinity() { return service.getSpec().getSessionAffinity(); } - public static List getServiceItems(KubernetesClient client) { - var serviceList = client.services().list().getItems(); - return serviceList.stream().map(service -> new K8sItemBuilder(ItemType.SERVICE, new ServiceItemAdapter(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java index cf4de9dc7..0e551ef0a 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java @@ -1,17 +1,9 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import de.bonndan.nivio.input.ItemType; -import de.bonndan.nivio.input.kubernetes.K8sItem; -import de.bonndan.nivio.input.kubernetes.K8sItemBuilder; -import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.StatefulSet; -import io.fabric8.kubernetes.client.KubernetesClient; import org.springframework.lang.NonNull; -import java.util.List; -import java.util.stream.Collectors; - public class StatefulSetItemAdapter implements ItemAdapter { private final StatefulSet statefulSet; @@ -53,8 +45,5 @@ public Integer getReplicas() { return statefulSet.getSpec().getReplicas(); } - public static List getStatefulSetItems(KubernetesClient client) { - var statefulSetList = client.apps().statefulSets().list().getItems(); - return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(ItemType.STATEFULSET, new StatefulSetItemAdapter(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); - } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java index d4015a6dc..11343b563 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -10,13 +10,8 @@ public class BoolStatus implements Status { @Override public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { return statusMap.entrySet().stream().collect(Collectors.toMap( - pair -> "condition." + pair.getKey().toLowerCase(), - pair -> { - if (pair.getValue().toLowerCase(Locale.ROOT).equals("true")) { - return de.bonndan.nivio.assessment.Status.GREEN.toString(); - } else { - return de.bonndan.nivio.assessment.Status.RED.toString(); - } - })); + pair -> "k8s.boolcondition." + pair.getKey().toLowerCase(), + pair -> pair.getValue().toLowerCase(Locale.ROOT) + )); } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java index 27b4c9b9f..6d7ca7e56 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -4,37 +4,20 @@ import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; -import java.util.Collections; import java.util.Map; -import java.util.Objects; public class ReplicaStatus implements Status { @Override public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { - Integer replicaCount; - Integer replicaCountDesired; if (itemAdapter instanceof ReplicaSetItemAdapter) { var concreteItem = (ReplicaSetItemAdapter) itemAdapter; - replicaCount = concreteItem.getReadyReplicas(); - replicaCountDesired = concreteItem.getReplicas(); + return Map.of("k8s.replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else if (itemAdapter instanceof StatefulSetItemAdapter) { var concreteItem = (StatefulSetItemAdapter) itemAdapter; - replicaCount = concreteItem.getReadyReplicas(); - replicaCountDesired = concreteItem.getReplicas(); + return Map.of("k8s.replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else { return statusMap; } - var message = String.format("condition.%s of %s Pods are ready", replicaCount, replicaCountDesired); - if (replicaCount == null) { - return Collections.singletonMap("condition.ReadyReplicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); - } else if (replicaCountDesired == null) { - return Collections.singletonMap("condition.Replicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); - } else if (Objects.equals(replicaCount, replicaCountDesired)) { - return Collections.singletonMap("condition.all pods are ready", de.bonndan.nivio.assessment.Status.GREEN.toString()); - } else if (replicaCount == 0) { - return Collections.singletonMap(message, de.bonndan.nivio.assessment.Status.RED.toString()); - } else - return Collections.singletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); } } diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index b012067cf..eeb55a58f 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -184,10 +184,9 @@ public Set getRelations() { * * @param relation to add or replace */ - //TODO uncomment public void addOrReplace(@NonNull final Relation relation) { if (relation.getSource() != this && relation.getTarget() != this) { - //throw new IllegalArgumentException(String.format("Relation contains no reference to item.%s %s", relation.getIdentifier(), this)); + throw new IllegalArgumentException(String.format("Relation contains no reference to item.%s %s", relation.getIdentifier(), this)); } getSimilar(relation).map(relations::remove); diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 189026bbe..0e6148ef2 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -56,7 +56,9 @@ public enum Label { status("Prefix for status labels. Can be used as prefix for all other labels to mark a status for the label.", true), - condition("Prefix for condition labels.", true); + condition("Prefix for condition labels.", true), + + k8s("Prefix for k8s labels."); /** * Separator for label key parts. diff --git a/src/main/app/k8sLabelConfig.json b/src/main/resources/k8sLabelConfig.json similarity index 84% rename from src/main/app/k8sLabelConfig.json rename to src/main/resources/k8sLabelConfig.json index a0ea8c41b..b69db00fe 100644 --- a/src/main/app/k8sLabelConfig.json +++ b/src/main/resources/k8sLabelConfig.json @@ -2,6 +2,7 @@ "namespace": "default", "experimentalFeatureLabel": { "active": "true", + "min_matching_label": "2", "level": { "StatefulSetItem": "0", "DeploymentItem": "1" diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java similarity index 89% rename from src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java rename to src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java index d164adbe7..d0a64877d 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -class PersistentVolumeClaimDetailsTest { +class PersistentVolumeDetailsTest { PersistentVolumeDetails persistentVolumeDetails; PersistentVolumeItemAdapter itemAdapter; @@ -39,8 +39,8 @@ void testGetExtendedDetails() { @Test void testGetExtendedDetailsClassCastException() { - ServiceDetails serviceDetails = new ServiceDetails(new PersistentVolumeDetails(new DefaultDetails())); - Map result = serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + persistentVolumeDetails = new PersistentVolumeDetails(new ServiceDetails(new DefaultDetails())); + Map result = PersistentVolumeDetailsTest.this.persistentVolumeDetails.getExtendedDetails(Map.of(), itemAdapter); assertThat(result).isEqualTo(Map.of("creation", "creationTimestamp", "name", "name", "namespace", "namespace", "phase status", "phase", "reclaim policy", "persistentVolumeReclaimPolicy", "storage class", "testStorage", "storage mode", "testMode", "testCapacity", "8gi")); } From 23c9c75c9f854ca588eae8f70bd707158cb1b6a5 Mon Sep 17 00:00:00 2001 From: robert Date: Wed, 21 Jul 2021 17:24:12 +0200 Subject: [PATCH 114/310] Add tests --- .../input/kubernetes/status/BoolStatus.java | 4 +- .../kubernetes/status/ReplicaStatus.java | 3 +- .../input/kubernetes/CreateItemsTest.java | 151 ++++++++++++++++++ .../nivio/input/kubernetes/K8sItemTest.java | 69 ++++++++ .../input/kubernetes/KubernetesTest.java | 45 ------ .../details/DeploymentDetailsTest.java | 39 +++-- .../PersistentVolumeClaimDetailsTest.java | 38 +++++ .../details/PersistentVolumeDetailsTest.java | 26 ++- .../details/ServiceDetailsTest.java | 35 ++++ .../kubernetes/status/BoolStatusTest.java | 21 +++ .../kubernetes/status/ReplicaStatusTest.java | 43 +++++ 11 files changed, 415 insertions(+), 59 deletions(-) create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java delete mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java index 11343b563..73482359d 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -1,6 +1,8 @@ package de.bonndan.nivio.input.kubernetes.status; import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import java.util.Locale; import java.util.Map; @@ -8,7 +10,7 @@ public class BoolStatus implements Status { @Override - public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { + public Map getExtendedStatus(@NonNull Map statusMap, @Nullable ItemAdapter itemAdapter) { return statusMap.entrySet().stream().collect(Collectors.toMap( pair -> "k8s.boolcondition." + pair.getKey().toLowerCase(), pair -> pair.getValue().toLowerCase(Locale.ROOT) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java index 6d7ca7e56..14d4bb8fa 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -3,13 +3,14 @@ import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; +import org.springframework.lang.NonNull; import java.util.Map; public class ReplicaStatus implements Status { @Override - public Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter) { + public Map getExtendedStatus(@NonNull Map statusMap, @NonNull ItemAdapter itemAdapter) { if (itemAdapter instanceof ReplicaSetItemAdapter) { var concreteItem = (ReplicaSetItemAdapter) itemAdapter; return Map.of("k8s.replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java new file mode 100644 index 000000000..1a566abd2 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java @@ -0,0 +1,151 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.itemadapters.*; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +@EnableKubernetesMockClient(crud = true, https = false) +class CreateItemsTest { + KubernetesClient kubernetesClient; + + @BeforeEach + void setUp() { + } + + @Test + void getDeploymentItems() { + var deployment = new DeploymentBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.apps().deployments().create(deployment); + var deploymentList = CreateItems.getDeploymentItems(kubernetesClient); + assertThat(deploymentList).isNotNull(); + assertThat(deploymentList.size()).isEqualTo(1); + assertThat(deploymentList.get(0).getUid()).isEqualTo("testUid"); + assertThat(deploymentList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(deploymentList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.boolcondition.testtype", "teststatus", "name", "deployment", "namespace", "test", "strategy", "strategyType")); + assertThat(deploymentList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new DeploymentItemAdapter(deployment)); + assertThat(deploymentList.get(0).getType()).isEqualTo(ItemType.DEPLOYMENT); + } + + @Test + void getPersistentVolumeClaimItems() { + var persistentVolumeClaim = new PersistentVolumeClaimBuilder() + .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); + var persistentVolumeClaimList = CreateItems.getPersistentVolumeClaimItems(kubernetesClient); + assertThat(persistentVolumeClaimList).isNotNull(); + assertThat(persistentVolumeClaimList.size()).isEqualTo(1); + assertThat(persistentVolumeClaimList.get(0).getUid()).isEqualTo("testUid"); + assertThat(persistentVolumeClaimList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(persistentVolumeClaimList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolumeclaim", "namespace", "test", "phase status", "testPhase", "storage class", "testStorageName")); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new PersistentVolumeClaimItemAdapter(persistentVolumeClaim)); + assertThat(persistentVolumeClaimList.get(0).getType()).isEqualTo(ItemType.VOLUME); + } + + @Test + void getPersistentVolumeItems() { + var persistentVolume = new PersistentVolumeBuilder() + .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumes().create(persistentVolume); + var persistentVolumeList = CreateItems.getPersistentVolumeItems(kubernetesClient); + assertThat(persistentVolumeList).isNotNull(); + assertThat(persistentVolumeList.size()).isEqualTo(1); + assertThat(persistentVolumeList.get(0).getUid()).isEqualTo("testUid"); + assertThat(persistentVolumeList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(persistentVolumeList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolume", "namespace", "test", "phase status", "testPhase", "reclaim policy", "testReclaimPolicy", "storage class", "testStorageName", "storage mode", "testAccessMode", "testCapacity", "8Gi")); + assertThat(persistentVolumeList.get(0).getItemAdapter().getWrappedItem()).isEqualTo(persistentVolume); + assertThat(persistentVolumeList.get(0).getType()).isEqualTo(ItemType.VOLUME); + } + + @Test + void getPodItems() { + var pod = new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.pods().create(pod); + var podList = CreateItems.getPodItems(kubernetesClient); + assertThat(podList).isNotNull(); + assertThat(podList.size()).isEqualTo(1); + assertThat(podList.get(0).getUid()).isEqualTo("testUid"); + assertThat(podList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(podList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.boolcondition.testtype", "teststatus", "name", "pod", "namespace", "test")); + assertThat(podList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new PodItemAdapter(pod)); + assertThat(podList.get(0).getType()).isEqualTo(ItemType.POD); + } + + @Test + void getReplicaSetItems() { + var replicaSet = new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().replicaSets().create(replicaSet); + var replicaSetList = CreateItems.getReplicaSetItems(kubernetesClient); + assertThat(replicaSetList).isNotNull(); + assertThat(replicaSetList.size()).isEqualTo(1); + assertThat(replicaSetList.get(0).getUid()).isEqualTo("testUid"); + assertThat(replicaSetList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(replicaSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.replicacondition.replicas", "1;1", "name", "replicaSet", "namespace", "test")); + assertThat(replicaSetList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new ReplicaSetItemAdapter(replicaSet)); + assertThat(replicaSetList.get(0).getType()).isEqualTo(ItemType.REPLICASET); + } + + @Test + void getServiceItems() { + var service = new ServiceBuilder() + .withNewMetadata().withName("service").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withClusterIP("testIP").withNewType("testType").withSessionAffinity("testSessionAffinity").endSpec() + .build(); + kubernetesClient.services().create(service); + var serviceList = CreateItems.getServiceItems(kubernetesClient); + assertThat(serviceList).isNotNull(); + assertThat(serviceList.size()).isEqualTo(1); + assertThat(serviceList.get(0).getUid()).isEqualTo("testUid"); + assertThat(serviceList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(serviceList.get(0).getDetails()).isEqualTo(Map.of("cluster ip", "testIP", "creation", "testCreation", "name", "service", "namespace", "test", "service type", "testType", "session affinity", "testSessionAffinity")); + assertThat(serviceList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new ServiceItemAdapter(service)); + assertThat(serviceList.get(0).getType()).isEqualTo(ItemType.SERVICE); + } + + @Test + void getStatefulSetItems() { + var statefulSet = new StatefulSetBuilder() + .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().statefulSets().create(statefulSet); + var statefulSetList = CreateItems.getStatefulSetItems(kubernetesClient); + assertThat(statefulSetList).isNotNull(); + assertThat(statefulSetList.size()).isEqualTo(1); + assertThat(statefulSetList.get(0).getUid()).isEqualTo("testUid"); + assertThat(statefulSetList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(statefulSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.replicacondition.replicas", "1;1", "name", "statefulSet", "namespace", "test")); + assertThat(statefulSetList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new StatefulSetItemAdapter(statefulSet)); + assertThat(statefulSetList.get(0).getType()).isEqualTo(ItemType.STATEFULSET); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java new file mode 100644 index 000000000..e6c038beb --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java @@ -0,0 +1,69 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class K8sItemTest { + K8sItem k8sItem; + + @BeforeEach + void setUp() { + k8sItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build())).build(); + } + + @Test + void addGetOwner() { + assertThat(k8sItem.getOwner().size()).isZero(); + var ownerK8sItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build())).build(); + k8sItem.addOwner(ownerK8sItem); + assertThat(k8sItem.getOwner().size()).isOne(); + assertThat(k8sItem.getOwner()).containsExactly(ownerK8sItem); + } + + @Test + void addGetRelation() { + assertThat(k8sItem.getRelationDescriptionList().size()).isZero(); + var relationDescription = new RelationDescription("1", "2"); + k8sItem.addRelation(relationDescription); + assertThat(k8sItem.getRelationDescriptionList().size()).isOne(); + assertThat(k8sItem.getRelationDescriptionList()).containsExactly(relationDescription); + } + + @Test + void getGroup() { + assertThat(k8sItem.getGroup()).isEqualTo("pod"); + var ownerK8sItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build())).build(); + k8sItem.addOwner(ownerK8sItem); + assertThat(k8sItem.getGroup()).isEqualTo("replicaSet"); + } + + @Test + void getLevelDecorator() { + assertThat(k8sItem.getLevelDecorator()).isEqualToComparingFieldByField(new LevelDecorator(K8sJsonParser.getExperimentalLevel(k8sItem.getItemAdapter().getClass()))); + } + + @Test + void getName() { + assertThat(k8sItem.getName()).isEqualTo("pod"); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java deleted file mode 100644 index 21e75ebe1..000000000 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.bonndan.nivio.input.kubernetes; - -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.PodSpecBuilder; -import io.fabric8.kubernetes.api.model.PodStatusBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -@EnableKubernetesMockClient(crud = true) -public class KubernetesTest { - - static KubernetesClient client; - - @BeforeEach - void setup() { - List containers = new ArrayList<>(); - Container c1 = new Container(); - c1.setImage("postgres:9.5"); - c1.setName("mydb"); - containers.add(c1); - - var pod = new PodBuilder() - .withNewMetadata() - .withName("pod1") - .withNamespace("default") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec( - new PodSpecBuilder() - .withContainers(containers) - .withNodeName("node1") - .build() - ) - .withStatus(new PodStatusBuilder().build()) - .build(); - client.pods().inNamespace("default").create(pod); - - } -} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java index b0da92694..e9820777a 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java @@ -1,10 +1,17 @@ package de.bonndan.nivio.input.kubernetes.details; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.slf4j.LoggerFactory; +import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -12,19 +19,19 @@ class DeploymentDetailsTest { DeploymentDetails deploymentDetails; - DeploymentItemAdapter itemAdapter; @BeforeEach void setUp() { - itemAdapter = Mockito.mock(DeploymentItemAdapter.class); - Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); - Mockito.when(itemAdapter.getStrategyType()).thenReturn("strategyType"); - Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); - Mockito.when(itemAdapter.getName()).thenReturn("name"); + } @Test void testGetExtendedDetails() { + var itemAdapter = Mockito.mock(DeploymentItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getStrategyType()).thenReturn("strategyType"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); deploymentDetails = new DeploymentDetails(new DefaultDetails()); Map result = deploymentDetails.getExtendedDetails(Map.of(), itemAdapter); assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); @@ -32,9 +39,23 @@ void testGetExtendedDetails() { @Test void testGetExtendedDetailsClassCastException() { - ServiceDetails serviceDetails = new ServiceDetails(new DeploymentDetails(new DefaultDetails())); - Map result = serviceDetails.getExtendedDetails(Map.of(), itemAdapter); - assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(DeploymentDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new DeploymentDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java new file mode 100644 index 000000000..d088e3580 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java @@ -0,0 +1,38 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class PersistentVolumeClaimDetailsTest { + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(PersistentVolumeClaimDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new PersistentVolumeClaimDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java index d0a64877d..e7454dedf 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java @@ -1,10 +1,16 @@ package de.bonndan.nivio.input.kubernetes.details; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; import io.fabric8.kubernetes.api.model.Quantity; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; @@ -39,9 +45,23 @@ void testGetExtendedDetails() { @Test void testGetExtendedDetailsClassCastException() { - persistentVolumeDetails = new PersistentVolumeDetails(new ServiceDetails(new DefaultDetails())); - Map result = PersistentVolumeDetailsTest.this.persistentVolumeDetails.getExtendedDetails(Map.of(), itemAdapter); - assertThat(result).isEqualTo(Map.of("creation", "creationTimestamp", "name", "name", "namespace", "namespace", "phase status", "phase", "reclaim policy", "persistentVolumeReclaimPolicy", "storage class", "testStorage", "storage mode", "testMode", "testCapacity", "8gi")); + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(PersistentVolumeDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new PersistentVolumeDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); } diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java new file mode 100644 index 000000000..32d6a5f0d --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java @@ -0,0 +1,35 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ServiceDetailsTest { + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(DeploymentItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(ServiceDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new ServiceDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java new file mode 100644 index 000000000..6c62f49cc --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class BoolStatusTest { + + @Test + void getExtendedStatus() { + var boolStatus = new BoolStatus(); + var extendedStatus = boolStatus.getExtendedStatus(Map.of("testKey", "testValue"), Mockito.mock(ItemAdapter.class)); + assertThat(extendedStatus).isEqualTo(Map.of("k8s.boolcondition.testkey", "testvalue")); + extendedStatus = boolStatus.getExtendedStatus(Map.of("testKey", "testValue"), null); + assertThat(extendedStatus).isEqualTo(Map.of("k8s.boolcondition.testkey", "testvalue")); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java new file mode 100644 index 000000000..3881174f8 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java @@ -0,0 +1,43 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ReplicaStatusTest { + + @Test + void getExtendedStatusReplicaSet() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = Mockito.mock(ReplicaSetItemAdapter.class); + Mockito.when(itemAdapter.getReadyReplicas()).thenReturn(1); + Mockito.when(itemAdapter.getReplicas()).thenReturn(1); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of("k8s.replicacondition.replicas", "1;1")); + } + + @Test + void getExtendedStatusStatefulSet() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = Mockito.mock(StatefulSetItemAdapter.class); + Mockito.when(itemAdapter.getReadyReplicas()).thenReturn(1); + Mockito.when(itemAdapter.getReplicas()).thenReturn(1); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of("k8s.replicacondition.replicas", "1;1")); + } + + @Test + void getExtendedStatusItemAdapter() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = new DeploymentItemAdapter(new Deployment()); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of("testKey", "testValue")); + } +} \ No newline at end of file From f1b7d2b0c8576fd038ea7103a58b6bfbdde3ba8e Mon Sep 17 00:00:00 2001 From: robert Date: Thu, 22 Jul 2021 13:06:40 +0200 Subject: [PATCH 115/310] Improve tests --- .../schema/Models/LandscapeDescription.rst | 10 ++-- docs/source/schema/spec.json | 8 +-- .../InputFormatHandlerKubernetes.java | 14 ++--- .../itemadapters/DeploymentItemAdapter.java | 17 ++++-- .../kubernetes/itemadapters/ItemAdapter.java | 9 ++- .../PersistentVolumeClaimItemAdapter.java | 17 ++++-- .../PersistentVolumeItemAdapter.java | 17 ++++-- .../itemadapters/PodItemAdapter.java | 22 +++++-- .../itemadapters/ReplicaSetItemAdapter.java | 16 +++-- .../itemadapters/ServiceItemAdapter.java | 17 ++++-- .../itemadapters/StatefulSetItemAdapter.java | 16 +++-- .../input/kubernetes/CreateItemsTest.java | 58 +++++++++++++------ .../details/PersistentVolumeDetailsTest.java | 2 +- 13 files changed, 152 insertions(+), 71 deletions(-) diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index 807ed451f..c887e1a45 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,11 +63,6 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - color - String - @@ -83,6 +78,11 @@ LandscapeDescription - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 800e22315..176e56577 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -417,10 +417,6 @@ }, "description": "Additional labels for the landscape." }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" - }, "color": { "type": "string" }, @@ -435,6 +431,10 @@ "$ref": "#/components/schemas/ItemDescription" } }, + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" + }, "links": { "type": "object", "additionalProperties": { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index d40b4e3fe..ab0c31e41 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -5,10 +5,10 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.OwnerReference; -import io.fabric8.kubernetes.api.model.PersistentVolume; -import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; @@ -128,8 +128,8 @@ private List createItemDescription(List itemList) { private void crossReferenceLabel(ArrayList itemList) { itemList.forEach(ownedItem -> { var ownerList = itemList.stream().filter( - ownerItem -> CollectionUtils.intersection(Objects.requireNonNullElse(ownedItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values(), - Objects.requireNonNullElse(ownerItem.getItemAdapter().getWrappedItem().getMetadata().getLabels(), new HashMap()).values()) + ownerItem -> CollectionUtils.intersection(Objects.requireNonNullElse(ownedItem.getItemAdapter().getLabels(), new HashMap()).values(), + Objects.requireNonNullElse(ownerItem.getItemAdapter().getLabels(), new HashMap()).values()) .size() >= K8sJsonParser.getMinMatchingLevel() && ownerItem.getLevelDecorator().getLevel() != -1 && ownedItem.getLevelDecorator().getLevel() != -1 && (ownerItem.getLevelDecorator().getLevel() - ownedItem.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); ownerList.forEach(ownedItem::addOwner); @@ -139,7 +139,7 @@ private void crossReferenceLabel(ArrayList itemList) { private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { persistentVolumeClaimList.forEach(persistentVolume -> { var owners = new ArrayList(); - owners = (ArrayList) podList.stream().filter(pod -> ((Pod) pod.getItemAdapter().getWrappedItem()).getSpec().getVolumes().stream().anyMatch(volume -> volume.getPersistentVolumeClaim() != null && volume.getPersistentVolumeClaim().getClaimName().equals(persistentVolume.getName()))).collect(Collectors.toList()); + owners = (ArrayList) podList.stream().filter(pod -> ((PodItemAdapter) pod.getItemAdapter()).getVolumes().stream().anyMatch(volume -> volume.getPersistentVolumeClaim() != null && volume.getPersistentVolumeClaim().getClaimName().equals(persistentVolume.getName()))).collect(Collectors.toList()); owners.forEach(persistentVolume::addOwner); }); } @@ -147,14 +147,14 @@ private void crossReferenceVolumes(List persistentVolumeClaimList, List private void crossReferenceOwner(ArrayList itemList) { itemList.forEach(ownedItem -> { var owners = new ArrayList(); - owners = (ArrayList) itemList.stream().filter(ownerItem -> ownedItem.getItemAdapter().getWrappedItem().getMetadata().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(ownerItem.getUid())).collect(Collectors.toList()); + owners = (ArrayList) itemList.stream().filter(ownerItem -> ownedItem.getItemAdapter().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(ownerItem.getUid())).collect(Collectors.toList()); owners.forEach(ownedItem::addOwner); }); } private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { persistentVolumes.forEach(ownedItem -> { - var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolume) ownedItem.getItemAdapter().getWrappedItem()).getSpec().getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); + var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolumeItemAdapter) ownedItem.getItemAdapter()).getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); claimer.forEach(ownedItem::addOwner); }); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java index d6115ee2b..69edbef85 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java @@ -1,9 +1,11 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.apps.Deployment; -import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; public class DeploymentItemAdapter implements ItemAdapter { private final Deployment deployment; @@ -12,9 +14,14 @@ public DeploymentItemAdapter(Deployment deployment) { this.deployment = deployment; } - @NonNull - public HasMetadata getWrappedItem() { - return deployment; + @Override + public Map getLabels() { + return deployment.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return deployment.getMetadata().getOwnerReferences(); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java index 2f2dceeba..c81871b69 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java @@ -1,10 +1,13 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; + +import java.util.List; +import java.util.Map; public interface ItemAdapter { - HasMetadata getWrappedItem(); + Map getLabels(); String getUid(); @@ -13,4 +16,6 @@ public interface ItemAdapter { String getNamespace(); String getCreationTimestamp(); + + List getOwnerReferences(); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java index 58671e8b3..5cc47ddc1 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java @@ -1,8 +1,10 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; -import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; public class PersistentVolumeClaimItemAdapter implements ItemAdapter { private final PersistentVolumeClaim persistentVolumeClaim; @@ -11,9 +13,14 @@ public PersistentVolumeClaimItemAdapter(PersistentVolumeClaim persistentVolumeCl this.persistentVolumeClaim = persistentVolumeClaim; } - @NonNull - public HasMetadata getWrappedItem() { - return persistentVolumeClaim; + @Override + public Map getLabels() { + return persistentVolumeClaim.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return persistentVolumeClaim.getMetadata().getOwnerReferences(); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java index b00f700f7..89dced07f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java @@ -1,9 +1,9 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.ObjectReference; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.PersistentVolume; import io.fabric8.kubernetes.api.model.Quantity; -import org.springframework.lang.NonNull; import java.util.List; import java.util.Map; @@ -15,10 +15,14 @@ public PersistentVolumeItemAdapter(PersistentVolume persistentVolume) { this.persistentVolume = persistentVolume; } + @Override + public Map getLabels() { + return persistentVolume.getMetadata().getLabels(); + } - @NonNull - public HasMetadata getWrappedItem() { - return persistentVolume; + @Override + public List getOwnerReferences() { + return persistentVolume.getMetadata().getOwnerReferences(); } @Override @@ -61,5 +65,8 @@ public Map getCapacity() { return persistentVolume.getSpec().getCapacity(); } + public ObjectReference getClaimRef() { + return persistentVolume.getSpec().getClaimRef(); + } } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java index 6b7fb1353..cafe509cd 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java @@ -1,8 +1,11 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.Pod; -import org.springframework.lang.NonNull; +import io.fabric8.kubernetes.api.model.Volume; + +import java.util.List; +import java.util.Map; public class PodItemAdapter implements ItemAdapter { private final Pod pod; @@ -11,9 +14,14 @@ public PodItemAdapter(Pod pod) { this.pod = pod; } - @NonNull - public HasMetadata getWrappedItem() { - return pod; + @Override + public Map getLabels() { + return pod.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return pod.getMetadata().getOwnerReferences(); } @Override @@ -36,5 +44,9 @@ public String getCreationTimestamp() { return pod.getMetadata().getCreationTimestamp(); } + public List getVolumes() { + return pod.getSpec().getVolumes(); + } + } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java index 992221535..ebf8a7f92 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java @@ -1,9 +1,11 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; public class ReplicaSetItemAdapter implements ItemAdapter { private final ReplicaSet replicaSet; @@ -12,10 +14,14 @@ public ReplicaSetItemAdapter(ReplicaSet replicaSet) { this.replicaSet = replicaSet; } - @NonNull @Override - public HasMetadata getWrappedItem() { - return replicaSet; + public Map getLabels() { + return replicaSet.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return replicaSet.getMetadata().getOwnerReferences(); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java index 2b40b87b1..7fa8e8298 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java @@ -1,8 +1,10 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.Service; -import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; public class ServiceItemAdapter implements ItemAdapter { private final Service service; @@ -11,9 +13,14 @@ public ServiceItemAdapter(Service service) { this.service = service; } - @NonNull - public HasMetadata getWrappedItem() { - return service; + @Override + public Map getLabels() { + return service.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return service.getMetadata().getOwnerReferences(); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java index 0e551ef0a..b0bb658b2 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java @@ -1,8 +1,10 @@ package de.bonndan.nivio.input.kubernetes.itemadapters; -import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.apps.StatefulSet; -import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.Map; public class StatefulSetItemAdapter implements ItemAdapter { private final StatefulSet statefulSet; @@ -12,9 +14,13 @@ public StatefulSetItemAdapter(StatefulSet statefulSet) { } @Override - @NonNull - public HasMetadata getWrappedItem() { - return statefulSet; + public Map getLabels() { + return statefulSet.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return statefulSet.getMetadata().getOwnerReferences(); } @Override diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java index 1a566abd2..a5227b907 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java @@ -13,6 +13,7 @@ import java.util.Map; +import static java.util.Map.entry; import static org.assertj.core.api.Assertions.assertThat; @@ -27,14 +28,17 @@ void setUp() { @Test void getDeploymentItems() { var deployment = new DeploymentBuilder() - .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() .build(); kubernetesClient.apps().deployments().create(deployment); var deploymentList = CreateItems.getDeploymentItems(kubernetesClient); assertThat(deploymentList).isNotNull(); - assertThat(deploymentList.size()).isEqualTo(1); + assertThat(deploymentList.size()).isOne(); + assertThat(deploymentList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(deploymentList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(deploymentList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(deploymentList.get(0).getUid()).isEqualTo("testUid"); assertThat(deploymentList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(deploymentList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.boolcondition.testtype", "teststatus", "name", "deployment", "namespace", "test", "strategy", "strategyType")); @@ -45,14 +49,17 @@ void getDeploymentItems() { @Test void getPersistentVolumeClaimItems() { var persistentVolumeClaim = new PersistentVolumeClaimBuilder() - .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() .withNewSpec().withStorageClassName("testStorageName").endSpec() .withNewStatus().withNewPhase("testPhase").endStatus() .build(); kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); var persistentVolumeClaimList = CreateItems.getPersistentVolumeClaimItems(kubernetesClient); assertThat(persistentVolumeClaimList).isNotNull(); - assertThat(persistentVolumeClaimList.size()).isEqualTo(1); + assertThat(persistentVolumeClaimList.size()).isOne(); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(persistentVolumeClaimList.get(0).getUid()).isEqualTo("testUid"); assertThat(persistentVolumeClaimList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(persistentVolumeClaimList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolumeclaim", "namespace", "test", "phase status", "testPhase", "storage class", "testStorageName")); @@ -63,50 +70,61 @@ void getPersistentVolumeClaimItems() { @Test void getPersistentVolumeItems() { var persistentVolume = new PersistentVolumeBuilder() - .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() - .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).endSpec() + .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).withClaimRef(new ObjectReferenceBuilder().withUid("testClaimUid").build()).endSpec() .withNewStatus().withNewPhase("testPhase").endStatus() .build(); kubernetesClient.persistentVolumes().create(persistentVolume); var persistentVolumeList = CreateItems.getPersistentVolumeItems(kubernetesClient); assertThat(persistentVolumeList).isNotNull(); - assertThat(persistentVolumeList.size()).isEqualTo(1); + assertThat(persistentVolumeList.size()).isOne(); + assertThat(persistentVolumeList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(persistentVolumeList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(persistentVolumeList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(persistentVolumeList.get(0).getUid()).isEqualTo("testUid"); assertThat(persistentVolumeList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(persistentVolumeList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolume", "namespace", "test", "phase status", "testPhase", "reclaim policy", "testReclaimPolicy", "storage class", "testStorageName", "storage mode", "testAccessMode", "testCapacity", "8Gi")); - assertThat(persistentVolumeList.get(0).getItemAdapter().getWrappedItem()).isEqualTo(persistentVolume); assertThat(persistentVolumeList.get(0).getType()).isEqualTo(ItemType.VOLUME); + assertThat(((PersistentVolumeItemAdapter) persistentVolumeList.get(0).getItemAdapter()).getClaimRef().getUid()).isEqualTo("testClaimUid"); } @Test void getPodItems() { var pod = new PodBuilder() - .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() - .withNewSpec().endSpec() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().addNewVolume().withNewPersistentVolumeClaim().withNewClaimName("testClaimName").endPersistentVolumeClaim().endVolume().endSpec() .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() .build(); kubernetesClient.pods().create(pod); var podList = CreateItems.getPodItems(kubernetesClient); assertThat(podList).isNotNull(); - assertThat(podList.size()).isEqualTo(1); + assertThat(podList.size()).isOne(); + assertThat(podList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(podList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(podList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(podList.get(0).getUid()).isEqualTo("testUid"); assertThat(podList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(podList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.boolcondition.testtype", "teststatus", "name", "pod", "namespace", "test")); assertThat(podList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new PodItemAdapter(pod)); + assertThat(((PodItemAdapter) podList.get(0).getItemAdapter()).getVolumes().size()).isOne(); + assertThat(((PodItemAdapter) podList.get(0).getItemAdapter()).getVolumes().get(0).getPersistentVolumeClaim().getClaimName()).isEqualTo("testClaimName"); assertThat(podList.get(0).getType()).isEqualTo(ItemType.POD); } @Test void getReplicaSetItems() { var replicaSet = new ReplicaSetBuilder() - .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() .withNewSpec().withReplicas(1).endSpec() .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() .build(); kubernetesClient.apps().replicaSets().create(replicaSet); var replicaSetList = CreateItems.getReplicaSetItems(kubernetesClient); assertThat(replicaSetList).isNotNull(); - assertThat(replicaSetList.size()).isEqualTo(1); + assertThat(replicaSetList.size()).isOne(); + assertThat(replicaSetList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(replicaSetList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(replicaSetList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(replicaSetList.get(0).getUid()).isEqualTo("testUid"); assertThat(replicaSetList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(replicaSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.replicacondition.replicas", "1;1", "name", "replicaSet", "namespace", "test")); @@ -117,13 +135,16 @@ void getReplicaSetItems() { @Test void getServiceItems() { var service = new ServiceBuilder() - .withNewMetadata().withName("service").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewMetadata().withName("service").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() .withNewSpec().withClusterIP("testIP").withNewType("testType").withSessionAffinity("testSessionAffinity").endSpec() .build(); kubernetesClient.services().create(service); var serviceList = CreateItems.getServiceItems(kubernetesClient); assertThat(serviceList).isNotNull(); - assertThat(serviceList.size()).isEqualTo(1); + assertThat(serviceList.size()).isOne(); + assertThat(serviceList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(serviceList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(serviceList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(serviceList.get(0).getUid()).isEqualTo("testUid"); assertThat(serviceList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(serviceList.get(0).getDetails()).isEqualTo(Map.of("cluster ip", "testIP", "creation", "testCreation", "name", "service", "namespace", "test", "service type", "testType", "session affinity", "testSessionAffinity")); @@ -134,14 +155,17 @@ void getServiceItems() { @Test void getStatefulSetItems() { var statefulSet = new StatefulSetBuilder() - .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() .withNewSpec().withReplicas(1).endSpec() .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() .build(); kubernetesClient.apps().statefulSets().create(statefulSet); var statefulSetList = CreateItems.getStatefulSetItems(kubernetesClient); assertThat(statefulSetList).isNotNull(); - assertThat(statefulSetList.size()).isEqualTo(1); + assertThat(statefulSetList.size()).isOne(); + assertThat(statefulSetList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(statefulSetList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(statefulSetList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); assertThat(statefulSetList.get(0).getUid()).isEqualTo("testUid"); assertThat(statefulSetList.get(0).getClass()).isEqualTo(K8sItem.class); assertThat(statefulSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "k8s.replicacondition.replicas", "1;1", "name", "statefulSet", "namespace", "test")); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java index e7454dedf..500ff3cec 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java @@ -60,7 +60,7 @@ void testGetExtendedDetailsClassCastException() { serviceDetails.getExtendedDetails(Map.of(), itemAdapter); List logsList = listAppender.list; var className = itemAdapter.getClass().getCanonicalName(); - assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter are in unnamed module of loader 'app')"); assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); } From 3d67be1096d162856c0ca23943b6673cf1242788 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 22 Jul 2021 20:59:32 +0000 Subject: [PATCH 116/310] fix: upgrade io.fabric8:kubernetes-client from 5.0.2 to 5.5.0 Snyk has created this PR to upgrade io.fabric8:kubernetes-client from 5.0.2 to 5.5.0. See this package in Maven Repository: https://mvnrepository.com/artifact/io.fabric8/kubernetes-client/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8149050c8..12144cb7c 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ io.fabric8 kubernetes-client - 5.0.2 + 5.5.0 io.fabric8 From 94013f4daf60ae338f45907eb2b020adf6591ad7 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 23 Jul 2021 05:19:41 +0000 Subject: [PATCH 117/310] fix: upgrade @types/react from 16.14.8 to 16.14.10 Snyk has created this PR to upgrade @types/react from 16.14.8 to 16.14.10. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index 383ce441e..d494bc639 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -12,7 +12,7 @@ "@types/dateformat": "^3.0.1", "@types/jest": "^26.0.23", "@types/node": "^14.17.3", - "@types/react": "^16.14.6", + "@types/react": "^16.14.10", "@types/react-dom": "^16.9.13", "@types/react-html-parser": "^2.0.1", "@types/react-router-dom": "^5.1.7", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 1c974519f..12b85121d 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2285,10 +2285,10 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^16.14.6": - version "16.14.8" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.8.tgz#4aee3ab004cb98451917c9b7ada3c7d7e52db3fe" - integrity sha512-QN0/Qhmx+l4moe7WJuTxNiTsjBwlBGHqKGvInSQCBdo7Qio0VtOqwsC0Wq7q3PbJlB0cR4Y4CVo1OOe6BOsOmA== +"@types/react@^16.14.10": + version "16.14.11" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.11.tgz#992a0cd4b66b9f27315042b5d96e976717368f04" + integrity sha512-Don0MtsZZ3fjwTJ2BsoqkyOy7e176KplEAKOpr/4XDdzinlyJBn9yfsKn5mcSgn4kh1B22+3tBnzBC1z63ybtQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" From 919d9b25260591e96e6a428bfb1e93aee0aca1ab Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 23 Jul 2021 12:37:08 +0200 Subject: [PATCH 118/310] Add tests --- .../InputFormatHandlerKubernetes.java | 2 +- .../input/kubernetes/CreateItemsTest.java | 5 - .../InputFormatHandlerKubernetesTest.java | 115 ++++++++++++++++++ 3 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index ab0c31e41..1531178c7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -55,7 +55,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti this.client = getClient(reference.getUrl()); try { - client.getVersion(); + client.apps().deployments(); landscapeDescription.mergeItems(getItemDescription(client)); } catch (KubernetesClientException n) { LOGGER.error(n.getMessage()); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java index a5227b907..dce5dfa2f 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java @@ -8,7 +8,6 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Map; @@ -21,10 +20,6 @@ class CreateItemsTest { KubernetesClient kubernetesClient; - @BeforeEach - void setUp() { - } - @Test void getDeploymentItems() { var deployment = new DeploymentBuilder() diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java new file mode 100644 index 000000000..680f36989 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java @@ -0,0 +1,115 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.observation.InputFormatObserver; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; + +@EnableKubernetesMockClient(crud = true, https = false) +class InputFormatHandlerKubernetesTest { + KubernetesClient kubernetesClient; + InputFormatHandlerKubernetes inputFormatHandlerKubernetes; + + @BeforeEach + void setUp() { + SourceReference sourceReference = new SourceReference(null, "k8s"); + sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); + inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient)); + } + + @Test + void getFormats() { + assertThat(inputFormatHandlerKubernetes.getFormats()).containsAll(List.of("kubernetes", "k8s")); + } + + @Test + void applyData() throws MalformedURLException { + var landscapeDescription = new LandscapeDescription("k8sLandscapeTest"); + var url = new URL("https://dedica.team"); + var sourceReference = new SourceReference("https://dedica.team", ""); + inputFormatHandlerKubernetes.applyData(sourceReference, url, landscapeDescription); + assertThat(landscapeDescription.getItemDescriptions().all().size()).isZero(); + setK8sTestEnvironment(); + inputFormatHandlerKubernetes.applyData(sourceReference, url, landscapeDescription); + assertThat(landscapeDescription.getItemDescriptions().all().size()).isEqualTo(7); + assertThat(landscapeDescription.getItemDescriptions().find("deploymentUid", "deployment").orElseThrow().getRelations().size()).isZero(); + assertThat(landscapeDescription.getItemDescriptions().find("replicaSetUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("deploymentUid"); + assertThat(landscapeDescription.getItemDescriptions().find("replicaSetUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("replicaSetUid"); + assertThat(landscapeDescription.getItemDescriptions().find("podUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("replicaSetUid"); + assertThat(landscapeDescription.getItemDescriptions().find("podUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("serviceUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("deploymentUid"); + assertThat(landscapeDescription.getItemDescriptions().find("serviceUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("serviceUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("persistentVolumeClaimUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeClaimUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeClaimUid"); + } + + private void setK8sTestEnvironment() { + var service = new ServiceBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("serviceUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withClusterIP("testIP").withNewType("testType").withSessionAffinity("testSessionAffinity").endSpec() + .build(); + kubernetesClient.services().create(service); + var deployment = new DeploymentBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("deploymentUid").withLabels(Map.of("testLabelKey", "testLabelValue", "1", "2")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.apps().deployments().create(deployment); + var replicaSet = new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("replicaSetUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("deploymentUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().replicaSets().create(replicaSet); + var statefulSet = new StatefulSetBuilder() + .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("statefulSetUid").withLabels(Map.of("testLabelKey", "testLabelValue", "1", "2")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().statefulSets().create(statefulSet); + var pod = new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("podUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("replicaSetUid").build()).withNamespace("test").endMetadata() + .withNewSpec().addNewVolume().withNewPersistentVolumeClaim().withNewClaimName("persistentvolumeclaim").endPersistentVolumeClaim().endVolume().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.pods().create(pod); + var persistentVolumeClaim = new PersistentVolumeClaimBuilder() + .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("persistentVolumeClaimUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); + var persistentVolume = new PersistentVolumeBuilder() + .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("persistentVolumeUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).withClaimRef(new ObjectReferenceBuilder().withUid("persistentVolumeClaimUid").build()).endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumes().create(persistentVolume); + } + + @Test + void getObserver() { + assertNull(inputFormatHandlerKubernetes.getObserver(Mockito.mock(InputFormatObserver.class), Mockito.mock(SourceReference.class))); + } +} \ No newline at end of file From 3718329b25150c3db84a7a20de64bac418f3a6af Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 23 Jul 2021 15:07:19 +0200 Subject: [PATCH 119/310] Change KubernetesKPI Add KubernetesKPI test --- .../nivio/assessment/kpi/KubernetesKPI.java | 23 +++++- .../java/de/bonndan/nivio/model/Label.java | 2 +- .../assessment/kpi/KubernetesKpiTest.java | 75 +++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index 15145a3b7..3ff617923 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -6,6 +6,8 @@ import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; import org.apache.commons.collections.map.SingletonMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.util.ObjectUtils; @@ -13,8 +15,10 @@ import java.util.concurrent.atomic.AtomicInteger; public class KubernetesKPI implements KPI { + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesKPI.class); public static final String IDENTIFIER = "k8s"; + private boolean enabled = true; @Override @NonNull @@ -33,7 +37,9 @@ public List getStatusValues(Component component) { statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message)); } else if (message.startsWith("replicacondition.")) { var splitValue = value.split(";"); - var replicaCondition = replicaCondition(Integer.parseInt(splitValue[0]), Integer.parseInt(splitValue[1])); + var replicaCount = getIntegerValue(splitValue, 0); + var replicaCountDesired = getIntegerValue(splitValue, 1); + var replicaCondition = replicaCondition(replicaCount, replicaCountDesired); statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(String.valueOf(replicaCondition.getValue())), String.valueOf(replicaCondition.getKey()))); } else { statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(value), message)); @@ -44,6 +50,15 @@ public List getStatusValues(Component component) { } + private Integer getIntegerValue(String[] splitValue, int position) { + try { + return Integer.parseInt(splitValue[position]); + } catch (NumberFormatException e) { + LOGGER.warn(e.getMessage()); + } + return null; + } + private String boolCondition(String flag) { if (flag.toLowerCase(Locale.ROOT).equals("true")) { return de.bonndan.nivio.assessment.Status.GREEN.toString(); @@ -73,7 +88,7 @@ public String getDescription() { @Override public boolean isEnabled() { - return true; + return enabled; } @Override @@ -85,4 +100,8 @@ public Map getRanges() { public Map> getMatches() { return null; } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } } diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 0e6148ef2..98861d903 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -58,7 +58,7 @@ public enum Label { condition("Prefix for condition labels.", true), - k8s("Prefix for k8s labels."); + k8s("Prefix for k8s labels.", true); /** * Separator for label key parts. diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java new file mode 100644 index 000000000..8382ecf44 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java @@ -0,0 +1,75 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.input.dto.ItemDescription; +import de.bonndan.nivio.model.Component; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; + +import static org.assertj.core.api.Assertions.assertThat; + +class KubernetesKpiTest { + KubernetesKPI kubernetesKPI; + + @BeforeEach + void setUp() { + kubernetesKPI = new KubernetesKPI(); + } + + @Test + void getStatusValues() { + assertThat(kubernetesKPI.getStatusValues(Mockito.mock(Component.class)).getClass()).isEqualTo(ArrayList.class); + var itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.boolcondition.test", "true"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.boolcondition.test", "false"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.replicacondition.test", "a;1"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("ReadyReplicas count was null"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.replicacondition.test", "1;a"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("Replicas count was null"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.replicacondition.test", "2;2"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("all pods are ready"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.replicacondition.test", "1;2"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.YELLOW); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("1 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.replicacondition.test", "0;2"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("0 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + + itemDescription = new ItemDescription(); + itemDescription.setLabel("k8s.testcondition.test", Status.GREEN.toString()); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("testcondition.test"); + assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void testGetSetEnabled() { + kubernetesKPI.setEnabled(false); + assertThat(kubernetesKPI.isEnabled()).isFalse(); + } +} From 96da79fe354da08e8482b01827d4e6dd905b4320 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 26 Jul 2021 13:29:41 +0200 Subject: [PATCH 120/310] Change K8sJsonParser Add tests for K8sJsonParser and K8sConfig --- .../nivio/input/kubernetes/K8sConfig.java | 42 +++++++++++ .../nivio/input/kubernetes/K8sJsonParser.java | 75 ++++++------------- src/main/resources/k8sLabelConfig.json | 13 ++-- .../nivio/input/kubernetes/K8sConfigTest.java | 17 +++++ 4 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java create mode 100644 src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java new file mode 100644 index 000000000..4ff909175 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.input.kubernetes; + +import java.util.Map; + +public class K8sConfig { + private boolean active; + private int minMatchingLabel; + private Map level; + + public K8sConfig() { + } + + public K8sConfig(boolean active, int minMatchingLabel, Map level) { + this.active = active; + this.minMatchingLabel = minMatchingLabel; + this.level = level; + } + + public boolean isActive() { + return active; + } + + public int getMinMatchingLabel() { + return minMatchingLabel; + } + + public Map getLevel() { + return level; + } + + public void setMinMatchingLabel(int minMatchingLabel) { + this.minMatchingLabel = minMatchingLabel; + } + + public void setLevel(Map level) { + this.level = level; + } + + public void setActive(boolean active) { + this.active = active; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java index 0c707efba..220d16e14 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -1,82 +1,55 @@ package de.bonndan.nivio.input.kubernetes; +import com.fasterxml.jackson.databind.ObjectMapper; import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; -import java.io.FileReader; -import java.util.HashMap; +import java.io.File; +import java.util.Map; /** * Parses config values for the crossReferenceLabel feature */ -@Service public class K8sJsonParser { private static final Logger LOGGER = LoggerFactory.getLogger(K8sJsonParser.class); - private static final HashMap cacheMap = new HashMap<>(); - private static final String JSONLABEL = "experimentalFeatureLabel"; private static final String FILEPATH = "src/main/resources/k8sLabelConfig.json"; + private static K8sConfig k8sConfig = null; private K8sJsonParser() { } - public static boolean getExperimentalActive() { - var parser = new JSONParser(); - var active = false; - try { - var obj = parser.parse(new FileReader(FILEPATH)); - var jsonObject = (JSONObject) obj; - var companyList = (JSONObject) jsonObject.get(JSONLABEL); - active = Boolean.parseBoolean(companyList.get("active").toString()); - } catch (Exception e) { - LOGGER.warn(e.getMessage()); + private static K8sConfig getK8sConfig() { + if (k8sConfig != null) { + return k8sConfig; + } else { + try { + var testMapper = new ObjectMapper(); + k8sConfig = testMapper.readValue(new File(FILEPATH), K8sConfig.class); + return k8sConfig; + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } } - return active; + k8sConfig = new K8sConfig(false, 0, Map.of()); + return k8sConfig; + } + + public static boolean getExperimentalActive() { + return getK8sConfig().isActive(); } public static int getMinMatchingLevel() { - var parser = new JSONParser(); - var minMatchingLabels = 4; - try { - var obj = parser.parse(new FileReader(FILEPATH)); - var jsonObject = (JSONObject) obj; - var companyList = (JSONObject) jsonObject.get(JSONLABEL); - minMatchingLabels = Integer.parseInt(companyList.get("min_matching_label").toString()); - } catch (Exception e) { - LOGGER.warn(e.getMessage()); - } - return minMatchingLabels; + return getK8sConfig().getMinMatchingLabel(); } public static int getExperimentalLevel(Class classToParse) { - var objectName = classToParse.getSimpleName(); - if (cacheMap.containsKey(objectName)) { - return cacheMap.get(objectName); - } else { - return getExperimentalLevelFromJSON(objectName); - } + return getExperimentalLevelFromJSON(classToParse.getSimpleName()); } private static int getExperimentalLevelFromJSON(String objectName) { - var parser = new JSONParser(); - try { - var obj = parser.parse(new FileReader(FILEPATH)); - var jsonObject = (JSONObject) obj; - var experimentalFeature = (JSONObject) jsonObject.get(JSONLABEL); - var level = (JSONObject) experimentalFeature.get("level"); - var classLevel = level.get(objectName); - var finalLevel = Integer.parseInt(String.valueOf(classLevel)); - cacheMap.put(objectName, finalLevel); - return finalLevel; - } catch (Exception e) { - LOGGER.info(String.format("No value for %s in config file found", objectName)); - } - cacheMap.put(objectName, -1); - return -1; + return getK8sConfig().getLevel().getOrDefault(objectName, -1); } } diff --git a/src/main/resources/k8sLabelConfig.json b/src/main/resources/k8sLabelConfig.json index b69db00fe..7990880ee 100644 --- a/src/main/resources/k8sLabelConfig.json +++ b/src/main/resources/k8sLabelConfig.json @@ -1,11 +1,8 @@ { - "namespace": "default", - "experimentalFeatureLabel": { - "active": "true", - "min_matching_label": "2", - "level": { - "StatefulSetItem": "0", - "DeploymentItem": "1" - } + "active": true, + "minMatchingLabel": 2, + "level": { + "DeploymentItemAdapter": 1, + "StatefulSetItemAdapter": 0 } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java new file mode 100644 index 000000000..ff89b31af --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java @@ -0,0 +1,17 @@ +package de.bonndan.nivio.input.kubernetes; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class K8sConfigTest { + @Test + void testConstructor() { + var testConfig = new K8sConfig(true, 2, Map.of()); + assertThat(testConfig.isActive()).isTrue(); + assertThat(testConfig.getMinMatchingLabel()).isEqualTo(2); + assertThat(testConfig.getLevel()).isEmpty(); + } +} \ No newline at end of file From a5151d1cc664d547a733c543cf8761d0ed021550 Mon Sep 17 00:00:00 2001 From: robrobert99 <84507051+robrobert99@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:41:14 +0200 Subject: [PATCH 121/310] Update src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java Co-authored-by: Daniel Pozzi --- src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java index d07a55871..618600175 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -12,7 +12,6 @@ * The K8sItem Class is intended to unify the K8s Objects up to an certain point and to store relation data between those. */ - public class K8sItem { private final List relationDescriptionList = new ArrayList<>(); private final Map labelMap = new HashMap<>(); @@ -99,4 +98,3 @@ public ItemAdapter getItemAdapter() { } } - From 7596118cb1f6e913fc00a4b857a83339095ecbf4 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 26 Jul 2021 16:32:12 +0200 Subject: [PATCH 122/310] Change KubernetesKPI and K8sJsonParser --- docs/source/inc_labels.rst | 1 - src/main/app/src/labels.json | 1 - .../nivio/assessment/kpi/KubernetesKPI.java | 44 +++++++++++-------- .../nivio/input/kubernetes/K8sJsonParser.java | 6 ++- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index 58bf07f39..a501de5da 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -5,7 +5,6 @@ * ``frameworks`` A comma-separated list of frameworks as key-value pairs (key is name, value is version). * ``health`` Description of the item's health status. * ``icon`` Icon/image (for displaying purposes). -* ``k8s`` Prefix for k8s labels. * ``layer`` A technical layer. * ``lifecycle`` A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``). * ``note`` A custom note. diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index 635b98963..4ebe3976f 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -6,7 +6,6 @@ "frameworks": "A comma-separated list of frameworks as key-value pairs (key is name, value is version).", "health": "Description of the item's health status.", "icon": "Icon/image (for displaying purposes).", - "k8s": "Prefix for k8s labels.", "layer": "A technical layer.", "lifecycle": "A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).", "note": "A custom note.", diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index 3ff617923..54994be6b 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -30,21 +30,24 @@ public List getStatusValues(Component component) { var statusList = new ArrayList(); var counter = new AtomicInteger(0); ((Labeled) component).getLabels(Label.k8s).forEach((key, value) -> { - if (!ObjectUtils.isEmpty(value)) { - var message = key.replaceFirst("k8s.", ""); - if (message.startsWith("boolcondition.")) { - message = message.replaceFirst("boolcondition.", ""); - statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message)); - } else if (message.startsWith("replicacondition.")) { - var splitValue = value.split(";"); - var replicaCount = getIntegerValue(splitValue, 0); - var replicaCountDesired = getIntegerValue(splitValue, 1); - var replicaCondition = replicaCondition(replicaCount, replicaCountDesired); - statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(String.valueOf(replicaCondition.getValue())), String.valueOf(replicaCondition.getKey()))); - } else { - statusList.add(new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(value), message)); - } + if (ObjectUtils.isEmpty(value)) { + return; } + StatusValue statusValue; + var message = key.replaceFirst("k8s.", ""); + if (message.startsWith("boolcondition.")) { + message = message.replaceFirst("boolcondition.", ""); + statusValue = new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message); + } else if (message.startsWith("replicacondition.")) { + var splitValue = value.split(";"); + var replicaCount = getIntegerValue(splitValue, 0); + var replicaCountDesired = getIntegerValue(splitValue, 1); + var replicaCondition = replicaCondition(replicaCount, replicaCountDesired); + statusValue = new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(String.valueOf(replicaCondition.getValue())), String.valueOf(replicaCondition.getKey())); + } else { + statusValue = new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(value), message); + } + statusList.add(statusValue); }); return statusList; @@ -71,14 +74,17 @@ private SingletonMap replicaCondition(Integer replicaCount, Integer replicaCount var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); if (replicaCount == null) { return new SingletonMap("ReadyReplicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); - } else if (replicaCountDesired == null) { + } + if (replicaCountDesired == null) { return new SingletonMap("Replicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); - } else if (Objects.equals(replicaCount, replicaCountDesired)) { + } + if (Objects.equals(replicaCount, replicaCountDesired)) { return new SingletonMap("all pods are ready", de.bonndan.nivio.assessment.Status.GREEN.toString()); - } else if (replicaCount == 0) { + } + if (replicaCount == 0) { return new SingletonMap(message, de.bonndan.nivio.assessment.Status.RED.toString()); - } else - return new SingletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); + } + return new SingletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java index 220d16e14..660cccd28 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -16,7 +16,11 @@ public class K8sJsonParser { private static final Logger LOGGER = LoggerFactory.getLogger(K8sJsonParser.class); private static final String FILEPATH = "src/main/resources/k8sLabelConfig.json"; - private static K8sConfig k8sConfig = null; + private static K8sConfig k8sConfig; + + static { + k8sConfig = getK8sConfig(); + } private K8sJsonParser() { } From f8f28d73c99e85043e23b415b53faf2bc0534c69 Mon Sep 17 00:00:00 2001 From: robert Date: Tue, 27 Jul 2021 14:56:04 +0200 Subject: [PATCH 123/310] Change Seed back to the pet_clinic example --- src/main/java/de/bonndan/nivio/input/Seed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index 63f0884c4..cadc889b2 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -70,7 +70,7 @@ public List getDemoFiles() { Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { - demoFiles.add(new File(absPath + "/src/test/resources/example/example_k8s.yml").toURI().toURL()); + demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); if (value.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); From d245c632c22be759b8190c136c96e4ba124052c9 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 01:25:01 +0000 Subject: [PATCH 124/310] fix: upgrade com.opencsv:opencsv from 5.4 to 5.5 Snyk has created this PR to upgrade com.opencsv:opencsv from 5.4 to 5.5. See this package in Maven Repository: https://mvnrepository.com/artifact/com.opencsv/opencsv/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8149050c8..77eb533ed 100644 --- a/pom.xml +++ b/pom.xml @@ -237,7 +237,7 @@ com.opencsv opencsv - 5.4 + 5.5 From c8d5197eda36930d98562ce2e84be715a38bf6c0 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 01:25:04 +0000 Subject: [PATCH 125/310] fix: upgrade org.gitlab4j:gitlab4j-api from 4.16.0 to 4.17.0 Snyk has created this PR to upgrade org.gitlab4j:gitlab4j-api from 4.16.0 to 4.17.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.gitlab4j/gitlab4j-api/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8149050c8..2201ddba5 100644 --- a/pom.xml +++ b/pom.xml @@ -257,7 +257,7 @@ org.gitlab4j gitlab4j-api - 4.16.0 + 4.17.0 From 3ce2d130096e081161daebecb5d15809386f27e4 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 19:51:12 +0000 Subject: [PATCH 126/310] fix: upgrade @types/jest from 26.0.23 to 26.0.24 Snyk has created this PR to upgrade @types/jest from 26.0.23 to 26.0.24. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index d494bc639..64831e211 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -10,7 +10,7 @@ "@mdi/svg": "^5.9.55", "@stomp/stompjs": "^5.4.4", "@types/dateformat": "^3.0.1", - "@types/jest": "^26.0.23", + "@types/jest": "^26.0.24", "@types/node": "^14.17.3", "@types/react": "^16.14.10", "@types/react-dom": "^16.9.13", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 12b85121d..1be18d528 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2153,10 +2153,10 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" -"@types/jest@^26.0.23": - version "26.0.23" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.23.tgz#a1b7eab3c503b80451d019efb588ec63522ee4e7" - integrity sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA== +"@types/jest@^26.0.24": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" From afef9e8a9ec2c9fb06f31e99b5ba5a7b6c51b27b Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 19:51:15 +0000 Subject: [PATCH 127/310] fix: upgrade @types/react-html-parser from 2.0.1 to 2.0.2 Snyk has created this PR to upgrade @types/react-html-parser from 2.0.1 to 2.0.2. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index d494bc639..936e6b732 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -14,7 +14,7 @@ "@types/node": "^14.17.3", "@types/react": "^16.14.10", "@types/react-dom": "^16.9.13", - "@types/react-html-parser": "^2.0.1", + "@types/react-html-parser": "^2.0.2", "@types/react-router-dom": "^5.1.7", "@types/react-svg-pan-zoom": "^3.3.1", "@types/react-transition-group": "^4.4.1", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 12b85121d..12a2e467e 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2223,10 +2223,10 @@ dependencies: "@types/react" "^16" -"@types/react-html-parser@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/react-html-parser/-/react-html-parser-2.0.1.tgz#2d9002ac5bf1adf9aff8eae77ace5488bd78c98d" - integrity sha512-Lyw0AtG3gahw78CX2pzmzhKaoZCfJNzzuhhPsFVhzFrylMv8NaCmzYaPKglMv3RRHpwBbHuMOkVx0HiwGZKgSA== +"@types/react-html-parser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/react-html-parser/-/react-html-parser-2.0.2.tgz#9b7e1b99657967e614aebf3f87d78a3fd0a1602c" + integrity sha512-avS2QzBMCUTGO2+gi3rWG6WreuU8zhf4b5CbS11itYlvLbwt5wmxBqQN4/f2z/JR/6Kvdt8ohAxhztb8XQHdPQ== dependencies: "@types/htmlparser2" "*" "@types/react" "*" From b6ac3cd575366e9d0bc6277423ef5bf3f518289a Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 19:51:19 +0000 Subject: [PATCH 128/310] fix: upgrade @types/react-router-dom from 5.1.7 to 5.1.8 Snyk has created this PR to upgrade @types/react-router-dom from 5.1.7 to 5.1.8. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index d494bc639..a78328556 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -15,7 +15,7 @@ "@types/react": "^16.14.10", "@types/react-dom": "^16.9.13", "@types/react-html-parser": "^2.0.1", - "@types/react-router-dom": "^5.1.7", + "@types/react-router-dom": "^5.1.8", "@types/react-svg-pan-zoom": "^3.3.1", "@types/react-transition-group": "^4.4.1", "axios": "^0.21.1", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 12b85121d..eed2b2ecd 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2231,10 +2231,10 @@ "@types/htmlparser2" "*" "@types/react" "*" -"@types/react-router-dom@^5.1.7": - version "5.1.7" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271" - integrity sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg== +"@types/react-router-dom@^5.1.8": + version "5.1.8" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.8.tgz#bf3e1c8149b3d62eaa206d58599de82df0241192" + integrity sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw== dependencies: "@types/history" "*" "@types/react" "*" From d4cd99c73e196d01dfbd6326fcd01969159697f6 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 19:51:21 +0000 Subject: [PATCH 129/310] fix: upgrade @types/react-dom from 16.9.13 to 16.9.14 Snyk has created this PR to upgrade @types/react-dom from 16.9.13 to 16.9.14. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index d494bc639..5fc974f4a 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -13,7 +13,7 @@ "@types/jest": "^26.0.23", "@types/node": "^14.17.3", "@types/react": "^16.14.10", - "@types/react-dom": "^16.9.13", + "@types/react-dom": "^16.9.14", "@types/react-html-parser": "^2.0.1", "@types/react-router-dom": "^5.1.7", "@types/react-svg-pan-zoom": "^3.3.1", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 12b85121d..e0453262c 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2216,10 +2216,10 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-dom@^16.9.13": - version "16.9.13" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.13.tgz#5898f0ee68fe200685e6b61d3d7d8828692814d0" - integrity sha512-34Hr3XnmUSJbUVDxIw/e7dhQn2BJZhJmlAaPyPwfTQyuVS9mV/CeyghFcXyvkJXxI7notQJz8mF8FeCVvloJrA== +"@types/react-dom@^16.9.14": + version "16.9.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.14.tgz#674b8f116645fe5266b40b525777fc6bb8eb3bcd" + integrity sha512-FIX2AVmPTGP30OUJ+0vadeIFJJ07Mh1m+U0rxfgyW34p3rTlXI+nlenvAxNn4BP36YyI9IJ/+UJ7Wu22N1pI7A== dependencies: "@types/react" "^16" From 5abe542db47ab9f896862f75a5187e5e71425264 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 28 Jul 2021 19:53:04 +0000 Subject: [PATCH 130/310] fix: upgrade @material-ui/core from 4.11.4 to 4.12.1 Snyk has created this PR to upgrade @material-ui/core from 4.11.4 to 4.12.1. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index d494bc639..9d3671a95 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -4,7 +4,7 @@ "private": true, "homepage": "./", "dependencies": { - "@material-ui/core": "^4.11.4", + "@material-ui/core": "^4.12.1", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", "@mdi/svg": "^5.9.55", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 12b85121d..f41710d54 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -1657,14 +1657,14 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@material-ui/core@^4.11.4": - version "4.11.4" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.4.tgz#4fb9fe5dec5dcf780b687e3a40cff78b2b9640a4" - integrity sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg== +"@material-ui/core@^4.12.1": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.12.2.tgz#59a8b19f16b8c218d912f37f5ae70473c3c82c73" + integrity sha512-Q1npB8V73IC+eV2X6as+g71MpEGQwqKHUI2iujY62npk35V8nMx/bUXAHjv5kKG1BZ8s8XUWoG6s/VkjYPjjQA== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/styles" "^4.11.4" - "@material-ui/system" "^4.11.3" + "@material-ui/system" "^4.12.1" "@material-ui/types" "5.1.0" "@material-ui/utils" "^4.11.2" "@types/react-transition-group" "^4.2.0" @@ -1715,10 +1715,10 @@ jss-plugin-vendor-prefixer "^10.5.1" prop-types "^15.7.2" -"@material-ui/system@^4.11.3": - version "4.11.3" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.3.tgz#466bc14c9986798fd325665927c963eb47cc4143" - integrity sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw== +"@material-ui/system@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.12.1.tgz#2dd96c243f8c0a331b2bb6d46efd7771a399707c" + integrity sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/utils" "^4.11.2" From 702a6497de5d69642e183b8b1e42ef5c6fc6dd7f Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 30 Jul 2021 23:01:20 +0000 Subject: [PATCH 131/310] fix: upgrade com.fasterxml.jackson.core:jackson-databind from 2.11.2 to 2.12.4 Snyk has created this PR to upgrade com.fasterxml.jackson.core:jackson-databind from 2.11.2 to 2.12.4. See this package in Maven Repository: https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7d7b6367..ae2146071 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ com.fasterxml.jackson.core jackson-databind - 2.11.2 + 2.12.4 javax.xml.bind From e9dc25b8e64a33d061c757eb1ff7df65ddb0ba4c Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 31 Jul 2021 04:45:42 +0000 Subject: [PATCH 132/310] fix: upgrade @types/react-transition-group from 4.4.1 to 4.4.2 Snyk has created this PR to upgrade @types/react-transition-group from 4.4.1 to 4.4.2. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index 692c80c93..d2796676b 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -17,7 +17,7 @@ "@types/react-html-parser": "^2.0.2", "@types/react-router-dom": "^5.1.8", "@types/react-svg-pan-zoom": "^3.3.1", - "@types/react-transition-group": "^4.4.1", + "@types/react-transition-group": "^4.4.2", "axios": "^0.21.1", "classnames": "^2.3.0", "dateformat": "^3.0.3", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 0d9d6f37e..15c7a4056 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2262,10 +2262,10 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.1.tgz#e1a3cb278df7f47f17b5082b1b3da17170bd44b1" - integrity sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ== +"@types/react-transition-group@^4.4.2": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.2.tgz#38890fd9db68bf1f2252b99a942998dc7877c5b3" + integrity sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ== dependencies: "@types/react" "*" From 45d9a2d6b77ed968b93af8b3dcdfb166197478f5 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 31 Jul 2021 04:45:45 +0000 Subject: [PATCH 133/310] fix: upgrade @types/react-svg-pan-zoom from 3.3.1 to 3.3.2 Snyk has created this PR to upgrade @types/react-svg-pan-zoom from 3.3.1 to 3.3.2. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index 692c80c93..63d8e05b7 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -16,7 +16,7 @@ "@types/react-dom": "^16.9.14", "@types/react-html-parser": "^2.0.2", "@types/react-router-dom": "^5.1.8", - "@types/react-svg-pan-zoom": "^3.3.1", + "@types/react-svg-pan-zoom": "^3.3.2", "@types/react-transition-group": "^4.4.1", "axios": "^0.21.1", "classnames": "^2.3.0", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 0d9d6f37e..5dc4e72d2 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2248,10 +2248,10 @@ "@types/history" "*" "@types/react" "*" -"@types/react-svg-pan-zoom@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/react-svg-pan-zoom/-/react-svg-pan-zoom-3.3.1.tgz#ae210ffd20422515eaf5d54bfa8fe374be585b1e" - integrity sha512-N10C2gGqs6apsnTmmddCbAlNwb5VuX1DvosPV7NOmPPrSaKjMIRdgJ4luj9qipGHzafUU/T2JtM87RgvO/V+XA== +"@types/react-svg-pan-zoom@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@types/react-svg-pan-zoom/-/react-svg-pan-zoom-3.3.2.tgz#58a259db7c4c211880cc3c0759ed6f7c8aafe3bc" + integrity sha512-q1PVNhwaM8FaIv73hFfKgvqGzaExTtx9aBUi75lAJPK7TIhw8Ql990oE4RHQjIUmmxWU/lE/RSbv2c+2W/K5Sg== dependencies: "@types/react" "*" From 59b44b86f0f521d4c407186a121b26df16cf6795 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sat, 31 Jul 2021 08:20:29 +0200 Subject: [PATCH 134/310] bumped databind version, using ZonedDateTime instead of LocalDateTime --- pom.xml | 9 ++++++++- .../de/bonndan/nivio/assessment/Assessment.java | 8 ++++---- .../de/bonndan/nivio/config/ApplicationConfig.java | 6 ++++++ .../java/de/bonndan/nivio/input/ProcessLog.java | 13 ++++++------- .../de/bonndan/nivio/input/ProcessingEvent.java | 8 ++++---- src/main/java/de/bonndan/nivio/model/Landscape.java | 6 +++--- .../nivio/notification/EventNotification.java | 8 ++++---- 7 files changed, 35 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index ae2146071..ba7f33290 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ v1.22.4 1.12.0 8.8.2 + 2.12.4 dedica-team_nivio dedica-team https://sonarcloud.io @@ -51,11 +52,17 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml + ${jackson.version} com.fasterxml.jackson.core jackson-databind - 2.12.4 + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} javax.xml.bind diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessment.java b/src/main/java/de/bonndan/nivio/assessment/Assessment.java index 54d239926..ada6290e7 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessment.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessment.java @@ -3,7 +3,7 @@ import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.List; import java.util.Map; @@ -15,10 +15,10 @@ public class Assessment { private final Map> results; - private final LocalDateTime date; + private final ZonedDateTime date; public Assessment(Map> results) { - date = LocalDateTime.now(); + date = ZonedDateTime.now(); this.results = results; } @@ -26,7 +26,7 @@ public Map> getResults() { return results; } - public LocalDateTime getDate() { + public ZonedDateTime getDate() { return date; } } diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index b9853362e..f7c7dc00c 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -39,4 +40,9 @@ public LocalIcons getLocalIcons(@Value("${nivio.iconFolder:" + DEFAULT_ICONS_FOL return new LocalIcons(iconsFolder); } + @Bean + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return new Jackson2ObjectMapperBuilder(); + } + } diff --git a/src/main/java/de/bonndan/nivio/input/ProcessLog.java b/src/main/java/de/bonndan/nivio/input/ProcessLog.java index 24203ca4d..e8aebb30d 100644 --- a/src/main/java/de/bonndan/nivio/input/ProcessLog.java +++ b/src/main/java/de/bonndan/nivio/input/ProcessLog.java @@ -4,11 +4,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import de.bonndan.nivio.model.Landscape; import org.slf4j.Logger; import org.springframework.lang.NonNull; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -71,9 +70,9 @@ public List getMessages() { } @JsonIgnore - public LocalDateTime getLastUpdate() { + public ZonedDateTime getLastUpdate() { - if (messages.size() > 0) { + if (!messages.isEmpty()) { return messages.get(messages.size() - 1).date; } return null; @@ -86,18 +85,18 @@ public static class Entry { public final String message; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") - public final LocalDateTime date; + public final ZonedDateTime date; public Entry(String level, String message) { this.level = level; this.message = message; - this.date = LocalDateTime.now(); + this.date = ZonedDateTime.now(); } public Entry(String level, ProcessingException e) { this.level = level; this.message = e.getMessage(); - this.date = LocalDateTime.now(); + this.date = ZonedDateTime.now(); } } } diff --git a/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java b/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java index 7b649ebff..44f666816 100644 --- a/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java +++ b/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java @@ -4,8 +4,8 @@ import org.springframework.context.ApplicationEvent; import java.time.Instant; -import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; /** * Event that is emitted during processing of landscapes. @@ -15,7 +15,7 @@ public abstract class ProcessingEvent extends ApplicationEvent { public static final String LOG_LEVEL_INFO = "info"; public static final String LOG_LEVEL_ERROR = "error"; - public ProcessingEvent(FullyQualifiedIdentifier source) { + protected ProcessingEvent(FullyQualifiedIdentifier source) { super(source); } @@ -34,9 +34,9 @@ public ProcessingEvent(FullyQualifiedIdentifier source) { */ public abstract String getMessage(); - public LocalDateTime getDate() { + public ZonedDateTime getDate() { Instant instant = Instant.ofEpochMilli(getTimestamp()); - return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); } @Override diff --git a/src/main/java/de/bonndan/nivio/model/Landscape.java b/src/main/java/de/bonndan/nivio/model/Landscape.java index 969ca71de..6c89bc6c8 100644 --- a/src/main/java/de/bonndan/nivio/model/Landscape.java +++ b/src/main/java/de/bonndan/nivio/model/Landscape.java @@ -19,7 +19,7 @@ import org.springframework.util.StringUtils; import javax.validation.constraints.Pattern; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.*; import java.util.stream.Collectors; @@ -269,7 +269,7 @@ public Map getLinks() { } @JsonGetter("lastUpdate") - public LocalDateTime getLastUpdate() { + public ZonedDateTime getLastUpdate() { return this.processLog == null ? null : this.processLog.getLastUpdate(); } @@ -304,7 +304,7 @@ public SearchIndex getSearchIndex() { * @return all matched items */ public Set search(String queryString) { - if (StringUtils.isEmpty(queryString)) { + if (!StringUtils.hasLength(queryString)) { return Collections.emptySet(); } return items.retrieve(searchIndex.search(queryString)); diff --git a/src/main/java/de/bonndan/nivio/notification/EventNotification.java b/src/main/java/de/bonndan/nivio/notification/EventNotification.java index 0650b5fee..df4537270 100644 --- a/src/main/java/de/bonndan/nivio/notification/EventNotification.java +++ b/src/main/java/de/bonndan/nivio/notification/EventNotification.java @@ -12,8 +12,8 @@ import org.springframework.lang.Nullable; import java.time.Instant; -import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Objects; /** @@ -32,7 +32,7 @@ public class EventNotification { /** * @param processingEvent application event * @return api model - * @throws NullPointerException + * @throws NullPointerException if a required processing event field is empty */ public static EventNotification from(ProcessingEvent processingEvent) { return new EventNotification( @@ -113,9 +113,9 @@ public String getLandscape() { } @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") - public LocalDateTime getDate() { + public ZonedDateTime getDate() { Instant instant = Instant.ofEpochMilli(timestamp); - return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); } @Schema(description = "In case of ProcessingFinishedEvent a changelog is contained.") From 5e58879f58073b9077a85148efa2402c180a782b Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sat, 31 Jul 2021 10:43:42 +0200 Subject: [PATCH 135/310] fix config --- .../de/bonndan/nivio/config/ApplicationConfig.java | 14 ++++++++++++-- .../de/bonndan/nivio/output/RenderingTest.java | 5 ++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index f7c7dc00c..087249b1b 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -1,15 +1,21 @@ package de.bonndan.nivio.config; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer; import de.bonndan.nivio.input.Seed; import de.bonndan.nivio.output.icons.LocalIcons; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.lang.NonNull; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.time.ZonedDateTime; + import static de.bonndan.nivio.output.icons.LocalIcons.DEFAULT_ICONS_FOLDER; @Configuration @@ -19,7 +25,7 @@ public class ApplicationConfig { public WebMvcConfigurer configurer() { return new WebMvcConfigurer() { @Override - public void addCorsMappings(CorsRegistry registry) { + public void addCorsMappings(@NonNull CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("*"); } }; @@ -42,7 +48,11 @@ public LocalIcons getLocalIcons(@Value("${nivio.iconFolder:" + DEFAULT_ICONS_FOL @Bean public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { - return new Jackson2ObjectMapperBuilder(); + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(ZonedDateTime.class, ZonedDateTimeSerializer.INSTANCE); + return new Jackson2ObjectMapperBuilder() + .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .modulesToInstall(module); } } diff --git a/src/test/java/de/bonndan/nivio/output/RenderingTest.java b/src/test/java/de/bonndan/nivio/output/RenderingTest.java index 5b9fc82ae..576c9ecec 100644 --- a/src/test/java/de/bonndan/nivio/output/RenderingTest.java +++ b/src/test/java/de/bonndan/nivio/output/RenderingTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.config.ApplicationConfig; import de.bonndan.nivio.input.*; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.http.CachedResponse; @@ -43,11 +44,13 @@ public abstract class RenderingTest { protected Indexer indexer; protected LandscapeDescriptionFactory factory; protected HttpService httpService; + private ObjectMapper objectMapper; public void setup() throws URISyntaxException { landscapeRepository = new LandscapeRepository(); formatFactory = new InputFormatHandlerFactory(List.of(new InputFormatHandlerNivio(new FileFetcher(new HttpService())))); httpService = mock(HttpService.class); + objectMapper = new ApplicationConfig().jackson2ObjectMapperBuilder().build(); CachedResponse response = mock(CachedResponse.class); when(response.getBytes()).thenReturn("foo".getBytes()); @@ -89,7 +92,7 @@ private String toSVG(LayoutedComponent layoutedComponent, Assessment assessment, when(mapStyleSheetFactory.getMapStylesheet(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(""); File json = new File(filename + "_debug.json"); - new ObjectMapper().writeValue(json, layoutedComponent); + objectMapper.writeValue(json, layoutedComponent); SVGRenderer svgRenderer = new SVGRenderer(mapStyleSheetFactory); SVGDocument svg = svgRenderer.render(layoutedComponent, assessment, true); From 179566b86bfae66aadd1a6b84a15fb9a244fe1b0 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sun, 1 Aug 2021 02:35:28 +0000 Subject: [PATCH 136/310] fix: upgrade org.openapitools:openapi-generator from 5.1.1 to 5.2.0 Snyk has created this PR to upgrade org.openapitools:openapi-generator from 5.1.1 to 5.2.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.openapitools/openapi-generator/ See this project in Snyk: https://app.snyk.io/org/bonndan/project/57bbd428-b835-46d9-9362-8a5d20323947?utm_source=github&utm_medium=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba7f33290..ed01ffc9f 100644 --- a/pom.xml +++ b/pom.xml @@ -277,7 +277,7 @@ org.openapitools openapi-generator - 5.1.1 + 5.2.0 From 1a16e2aefe72981c71be77da3c3effd8b6262ae5 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sun, 1 Aug 2021 04:00:45 +0000 Subject: [PATCH 137/310] fix: upgrade @types/node from 14.17.4 to 14.17.5 Snyk has created this PR to upgrade @types/node from 14.17.4 to 14.17.5. See this package in npm: See this project in Snyk: https://app.snyk.io/org/bonndan/project/1de653dc-2773-49ea-b323-6c32373df9d1?utm_source=github&utm_medium=upgrade-pr --- src/main/app/package.json | 2 +- src/main/app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/app/package.json b/src/main/app/package.json index 36acf35f1..5810ca2e2 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -11,7 +11,7 @@ "@stomp/stompjs": "^5.4.4", "@types/dateformat": "^3.0.1", "@types/jest": "^26.0.24", - "@types/node": "^14.17.3", + "@types/node": "^14.17.5", "@types/react": "^16.14.10", "@types/react-dom": "^16.9.14", "@types/react-html-parser": "^2.0.2", diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index f906fd67f..2dd35fe0a 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -2186,10 +2186,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.24.tgz#b0f86f58564fa02a28b68f8b55d4cdec42e3b9d6" integrity sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA== -"@types/node@^14.17.3": - version "14.17.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.4.tgz#218712242446fc868d0e007af29a4408c7765bc0" - integrity sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A== +"@types/node@^14.17.5": + version "14.17.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.6.tgz#cc61c8361c89e70c468cda464d1fa3dd7e5ebd62" + integrity sha512-iBxsxU7eswQDGhlr3AiamBxOssaYxbM+NKXVil8jg9yFXvrfEFbDumLD/2dMTB+zYyg7w+Xjt8yuxfdbUHAtcQ== "@types/normalize-package-data@^2.4.0": version "2.4.0" From e809790f5249e64cb0566435c42c46179b41ad33 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 2 Aug 2021 11:36:39 +0200 Subject: [PATCH 138/310] Add Observer --- .../schema/Models/LandscapeDescription.rst | 10 ++-- docs/source/schema/spec.json | 8 +-- pom.xml | 2 +- .../java/de/bonndan/nivio/input/Seed.java | 2 +- .../input/kubernetes/KubernetesObserver.java | 56 +++++++++++++++++++ .../status/KubernetesObserverRegistry.java | 54 ++++++++++++++++++ 6 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java create mode 100644 src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..807ed451f 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,6 +63,11 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null * - color - String - @@ -78,11 +83,6 @@ LandscapeDescription - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 176e56577..800e22315 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -417,6 +417,10 @@ }, "description": "Additional labels for the landscape." }, + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" + }, "color": { "type": "string" }, @@ -431,10 +435,6 @@ "$ref": "#/components/schemas/ItemDescription" } }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" - }, "links": { "type": "object", "additionalProperties": { diff --git a/pom.xml b/pom.xml index d283465e8..0e5315623 100644 --- a/pom.xml +++ b/pom.xml @@ -180,7 +180,7 @@ io.fabric8 kubernetes-client - 5.0.2 + 5.6.0 io.fabric8 diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index cadc889b2..63f0884c4 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -70,7 +70,7 @@ public List getDemoFiles() { Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { - demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); + demoFiles.add(new File(absPath + "/src/test/resources/example/example_k8s.yml").toURI().toURL()); if (value.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java new file mode 100644 index 000000000..594099783 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java @@ -0,0 +1,56 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.IndexEvent; +import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.observation.InputFormatObserver; +import io.fabric8.kubernetes.api.model.events.v1.Event; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + + +public class KubernetesObserver implements InputFormatObserver { + + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesObserver.class); + + private final LandscapeDescription landscapeDescription; + private final ApplicationEventPublisher eventPublisher; + private final KubernetesClient kubernetesClient; + private List eventList = null; + + public KubernetesObserver(@NonNull final LandscapeDescription landscapeDescription, @NonNull final ApplicationEventPublisher eventPublisher, @NonNull final KubernetesClient kubernetesClient) { + this.landscapeDescription = landscapeDescription; + this.kubernetesClient = kubernetesClient; + this.eventPublisher = eventPublisher; + } + + @Override + public void run() { + while (true) { + if (eventList == null) { + eventList = kubernetesClient.events().v1().events().list().getItems(); + } else { + if (compareEvents(eventList, kubernetesClient.events().v1().events().list().getItems())) { + triggerChange(); + return; + } + } + } + } + + private boolean compareEvents(@NonNull List eventListOld, @NonNull List eventListNew) { + var eventListOldName = eventListOld.stream().map(event -> event.getMetadata().getName()).collect(Collectors.toList()); + var eventListNewName = eventListNew.stream().map(event -> event.getMetadata().getName()).collect(Collectors.toList()); + return eventListNewName.equals(eventListOldName); + } + + private void triggerChange() { + LOGGER.info("Kubernetes Observer published new IndexEvent"); + eventPublisher.publishEvent(new IndexEvent(landscapeDescription, "testMessage")); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java new file mode 100644 index 000000000..34b6dec9e --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java @@ -0,0 +1,54 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.ProcessingFinishedEvent; +import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.kubernetes.KubernetesObserver; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.observation.LandscapeObserverPool; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +@Service +public class KubernetesObserverRegistry { + + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesObserverRegistry.class); + + private final Map observerMap = new ConcurrentHashMap<>(); + + private final ApplicationEventPublisher applicationEventPublisher; + private final ThreadPoolTaskScheduler taskScheduler; + + public KubernetesObserverRegistry(ThreadPoolTaskScheduler taskScheduler, ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + this.taskScheduler = taskScheduler; + } + + @EventListener(ProcessingFinishedEvent.class) + public void onProcessingFinishedEvent(ProcessingFinishedEvent event) { + LandscapeDescription landscapeDescription = event.getInput(); + Landscape landscape = Objects.requireNonNull(event.getLandscape()); + + if (landscapeDescription == null) { + String msg = String.format("No landscape description (input) available. Landscape %s could not be registered for observation", landscape.getIdentifier()); + landscape.getLog().warn(msg); + LOGGER.warn(msg); + return; + } + + LandscapeObserverPool pool = observerMap.computeIfAbsent(landscape.getIdentifier(), s -> { + LOGGER.info("Registered landscape {} for observation.", landscapeDescription); + return new LandscapeObserverPool(taskScheduler, 30 * 1000); + }); + pool.updateObservers(List.of(new KubernetesObserver(landscapeDescription, applicationEventPublisher, new DefaultKubernetesClient()))); + } +} From 49f25d5bf137ef70c6a14960ea7a303dc7e51ece Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 2 Aug 2021 13:02:57 +0200 Subject: [PATCH 139/310] [#581] extracted k8s label prefix, omitting in api labels --- .../kubernetes/InputFormatHandlerKubernetes.java | 2 ++ .../nivio/input/kubernetes/status/BoolStatus.java | 4 +++- .../input/kubernetes/status/ReplicaStatus.java | 5 +++-- src/main/java/de/bonndan/nivio/model/Item.java | 4 +++- .../java/de/bonndan/nivio/model/ItemTest.java | 15 +++++++++++++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 1531178c7..5975153f7 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -34,6 +34,8 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { public static final String NAMESPACE = "namespace"; + public static final String LABEL_PREFIX = "k8s."; + private KubernetesClient client; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java index 73482359d..23c365d21 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.kubernetes.status; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -9,10 +10,11 @@ import java.util.stream.Collectors; public class BoolStatus implements Status { + @Override public Map getExtendedStatus(@NonNull Map statusMap, @Nullable ItemAdapter itemAdapter) { return statusMap.entrySet().stream().collect(Collectors.toMap( - pair -> "k8s.boolcondition." + pair.getKey().toLowerCase(), + pair -> InputFormatHandlerKubernetes.LABEL_PREFIX + "boolcondition." + pair.getKey().toLowerCase(), pair -> pair.getValue().toLowerCase(Locale.ROOT) )); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java index 14d4bb8fa..9421806f6 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input.kubernetes.status; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; @@ -13,10 +14,10 @@ public class ReplicaStatus implements Status { public Map getExtendedStatus(@NonNull Map statusMap, @NonNull ItemAdapter itemAdapter) { if (itemAdapter instanceof ReplicaSetItemAdapter) { var concreteItem = (ReplicaSetItemAdapter) itemAdapter; - return Map.of("k8s.replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + "replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else if (itemAdapter instanceof StatefulSetItemAdapter) { var concreteItem = (StatefulSetItemAdapter) itemAdapter; - return Map.of("k8s.replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + "replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else { return statusMap; } diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index eeb55a58f..7bba1c8f8 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -4,6 +4,7 @@ import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.input.ItemRelationProcessor; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.output.Color; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; @@ -160,10 +161,11 @@ public Map getLabels() { * Returns the labels without the internal ones (having prefixes). * * @return filtered labels + * @todo find a better way to exclude label "namespaces". Here we introduce unnecessary coupling. */ @JsonProperty("labels") public Map getJSONLabels() { - return Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG, Label.type.name(), Label.icon.name()); + return Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG, Label.type.name(), Label.icon.name(), InputFormatHandlerKubernetes.LABEL_PREFIX); } /** diff --git a/src/test/java/de/bonndan/nivio/model/ItemTest.java b/src/test/java/de/bonndan/nivio/model/ItemTest.java index df9d5550b..efc855237 100644 --- a/src/test/java/de/bonndan/nivio/model/ItemTest.java +++ b/src/test/java/de/bonndan/nivio/model/ItemTest.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.model; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import org.junit.jupiter.api.Test; import java.util.List; @@ -65,6 +66,20 @@ public void labelsAreNotGroupedInApi() { assertThat(labels).containsKey("foo.two"); } + @Test + public void labelsAreExcluded() { + + Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + + Item s1 = getTestItem("g1", "a", landscape); + s1.getLabels().put(InputFormatHandlerKubernetes.LABEL_PREFIX + "foo", "one"); + s1.getLabels().put(Label.type.name(), "two"); + + Map labels = s1.getJSONLabels(); + assertThat(labels).doesNotContainKey(InputFormatHandlerKubernetes.LABEL_PREFIX + "foo"); + assertThat(labels).doesNotContainKey(Label.type.name()); + } + @Test public void getChangesInLabels() { Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); From b1e025879d27b13ea3b72a8dda2aa21f51d380dc Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Mon, 2 Aug 2021 14:41:12 +0200 Subject: [PATCH 140/310] [#565] cleanup --- .../java/de/bonndan/nivio/input/dto/ItemDescription.java | 6 +++--- src/main/java/de/bonndan/nivio/model/Labeled.java | 2 +- .../java/de/bonndan/nivio/output/map/svg/SVGRelation.java | 3 ++- src/main/java/de/bonndan/nivio/search/SearchIndex.java | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index 2bf0426e5..d2c2370bf 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -246,9 +246,9 @@ public void setRelations(List relations) { */ public void addOrReplaceRelation(@NonNull final RelationDescription description) { RelationDescription relationDescription = Objects.requireNonNull(description).findMatching(this.relations) - .map(relationDescription1 -> { - relationDescription1.update(description); - return relationDescription1; + .map(existingRelation -> { + existingRelation.update(description); + return existingRelation; }) .orElse(description); this.relations.add(relationDescription); diff --git a/src/main/java/de/bonndan/nivio/model/Labeled.java b/src/main/java/de/bonndan/nivio/model/Labeled.java index 75a348321..1e86b90e6 100644 --- a/src/main/java/de/bonndan/nivio/model/Labeled.java +++ b/src/main/java/de/bonndan/nivio/model/Labeled.java @@ -205,7 +205,7 @@ default Map> indexedByPrefix(String prefix) { } /** - * ADd all non-null labels from source to target where target labels are not set. + * Add all non-null labels from source to target where target labels are not set. * * @param source label source * @param target target diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java index c6b24da51..29e7d9860 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java @@ -29,6 +29,7 @@ class SVGRelation extends Component { private static final Logger LOGGER = LoggerFactory.getLogger(SVGRelation.class); public static final String MARKER_ID = "arrow"; + public static final int BASIC_STROKE_WIDTH = 20; private final HexPath hexPath; private final String fill; @@ -87,7 +88,7 @@ public DomContent render() { shadow = SvgTagCreator.path() .attr("d", points) .attr("stroke", statusColor) - .attr("stroke-width", Math.round(20 * factor)); + .attr("stroke-width", Math.round(BASIC_STROKE_WIDTH * factor)); } ContainerTag path = SvgTagCreator.path() diff --git a/src/main/java/de/bonndan/nivio/search/SearchIndex.java b/src/main/java/de/bonndan/nivio/search/SearchIndex.java index 3de7aa8b0..dfbfd634d 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchIndex.java +++ b/src/main/java/de/bonndan/nivio/search/SearchIndex.java @@ -85,14 +85,14 @@ public void indexForSearch(@NonNull final Landscape landscape, @NonNull final As /** * Creates a search index based in a snapshot of current items state (later modifications won't be shown). */ - private void indexItems(Set items, Map> results) { + private void indexItems(Set items, Map> assessments) { try { FacetsConfig config = SearchDocumentFactory.getConfig(); TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoIndex, IndexWriterConfig.OpenMode.CREATE); IndexWriter writer = new IndexWriter(searchIndex, new IndexWriterConfig(new StandardAnalyzer())); writer.deleteAll(); for (Item item : items) { - writer.addDocument(config.build(taxoWriter, from(item, results.get(item.getFullyQualifiedIdentifier().toString())))); + writer.addDocument(config.build(taxoWriter, from(item, assessments.get(item.getFullyQualifiedIdentifier().toString())))); } IOUtils.close(writer, taxoWriter); } catch (IOException e) { From 9e579875f8d64cec000259b9692570bdd6b7cfad Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 2 Aug 2021 15:32:17 +0200 Subject: [PATCH 141/310] Improve minikube.md --- docs/k8s-minikube.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/k8s-minikube.md b/docs/k8s-minikube.md index 39bba01c4..dc957a6d7 100644 --- a/docs/k8s-minikube.md +++ b/docs/k8s-minikube.md @@ -39,15 +39,22 @@ kubectl create clusterrolebinding dashboard-admin-sa --clusterrole=cluster-admin kubectl get secrets kubectl describe secret dashboard-admin-sa-token-***** ``` -* enter the k8s dashboard: go to http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/. +* enter the k8s dashboard: go + to http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/. + +## Install example Helm Charts -## Install example Helm Charts * helm repo add bitnami https://charts.bitnami.com/bitnami * helm install redis bitnami/redis --set serviceType=NodePort * helm install nivio-wordpress bitnami/wordpress +## Change URL in K8s config file + +* change URL under sources to K8s API URL + ## Start nivio + ``` SEED=$(pwd)./src/test/resources/example/example_k8s.yml java -jar target/nivio.jar ``` From 4922dd85b001dee2ada478162e4972213ec6e57a Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 2 Aug 2021 15:38:10 +0200 Subject: [PATCH 142/310] Fix merge conflict between ZonedDateTime and LocalDateTime --- docs/source/schema/.openapi-generator/VERSION | 2 +- docs/source/schema/Models/ItemDescription.rst | 4 +- docs/source/schema/Models/KPIConfig.rst | 2 +- .../schema/Models/LandscapeDescription.rst | 14 +- docs/source/schema/spec.json | 146 ++++++++++-------- .../bonndan/nivio/assessment/Assessment.java | 5 +- 6 files changed, 91 insertions(+), 82 deletions(-) diff --git a/docs/source/schema/.openapi-generator/VERSION b/docs/source/schema/.openapi-generator/VERSION index acf69b48b..7cbea073b 100644 --- a/docs/source/schema/.openapi-generator/VERSION +++ b/docs/source/schema/.openapi-generator/VERSION @@ -1 +1 @@ -5.1.0 \ No newline at end of file +5.2.0 \ No newline at end of file diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..022f72838 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -83,12 +83,12 @@ List of configuration sources. Handled in the given order, latter extend/overwri - The lifecycle state of an item. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - statuses + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index 8838e6fc9..e170f09ad 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -21,7 +21,7 @@ The configuration of landscape specific key performance indicators that derive s * - label - String - Key of the label to evaluate - - optional, defaults to null + - **required**, defaults to null - costs * - messageTemplate - String diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index f906713fe..807ed451f 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,12 +63,17 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - icon + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null + * - color - String - - optional, defaults to null - null - * - color + * - icon - String - - optional, defaults to null @@ -78,11 +83,6 @@ LandscapeDescription - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - links - Map - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 60951921a..cdef264f8 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -191,39 +191,52 @@ "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", "example" : "4400FF" }, - "address" : { - "type" : "string", - "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." - }, - "type" : { - "type" : "string", - "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - "example" : "service|database|volume" - }, - "status" : { - "type" : "array", - "description" : "A list of statuses that works like hardcoded KPIs.", - "writeOnly" : true, - "items" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A list of statuses that works like hardcoded KPIs." + "address": { + "type": "string", + "description": "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." + }, + "type": { + "type": "string", + "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", + "example": "service|database|volume" + }, + "lifecycle": { + "type": "string", + "description": "The lifecycle state of an item.", + "writeOnly": true, + "enum": [ + "PLANNED", + "INTEGRATION", + "TEST", + "PRODUCTION", + "END_OF_LIFE", + "EOL" + ] + }, + "statuses": { + "type": "array", + "description": "A list of statuses that works like hardcoded KPIs.", + "writeOnly": true, + "items": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A list of statuses that works like hardcoded KPIs." }, - "description" : "A list of statuses that works like hardcoded KPIs." + "description": "A list of statuses that works like hardcoded KPIs." } }, - "statuses" : { - "type" : "array", - "description" : "A list of statuses that works like hardcoded KPIs.", - "writeOnly" : true, - "items" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A list of statuses that works like hardcoded KPIs." + "status": { + "type": "array", + "description": "A list of statuses that works like hardcoded KPIs.", + "writeOnly": true, + "items": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A list of statuses that works like hardcoded KPIs." }, - "description" : "A list of statuses that works like hardcoded KPIs." + "description": "A list of statuses that works like hardcoded KPIs." } }, "frameworks" : { @@ -237,12 +250,6 @@ "writeOnly" : true, "example" : "java: 8" }, - "lifecycle" : { - "type" : "string", - "description" : "The lifecycle state of an item.", - "writeOnly" : true, - "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] - }, "tags" : { "type" : "array", "items" : { @@ -261,16 +268,19 @@ "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." }, "KPIConfig" : { - "type" : "object", - "properties" : { - "description" : { - "type" : "string", - "description" : "Description of the purpose of the KPI" - }, - "label" : { - "type" : "string", - "description" : "Key of the label to evaluate", - "example" : "costs" + "required": [ + "label" + ], + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Description of the purpose of the KPI" + }, + "label": { + "type": "string", + "description": "Key of the label to evaluate", + "example": "costs" }, "messageTemplate" : { "type" : "string", @@ -397,36 +407,36 @@ "additionalProperties" : { "$ref" : "#/components/schemas/GroupDescription" }, - "description" : "Description of item groups (optional, can also be given in sources)." + "description": "Description of item groups (optional, can also be given in sources)." }, - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Additional labels for the landscape." + "labels": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Additional labels for the landscape." }, - "description" : "Additional labels for the landscape." + "description": "Additional labels for the landscape." }, - "items" : { - "type" : "array", - "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/ItemDescription" - } + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" }, - "partial" : { - "type" : "boolean", - "description" : "marks that the landscape is not complete, but an update" + "color": { + "type": "string" }, - "icon" : { - "type" : "string" + "icon": { + "type": "string" }, - "color" : { - "type" : "string" + "items": { + "type": "array", + "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", + "writeOnly": true, + "items": { + "$ref": "#/components/schemas/ItemDescription" + } }, - "links" : { - "type" : "object", + "links": { + "type": "object", "additionalProperties" : { "$ref" : "#/components/schemas/Link" }, diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessment.java b/src/main/java/de/bonndan/nivio/assessment/Assessment.java index cabf6b0fd..5ca6adffa 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessment.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessment.java @@ -1,9 +1,8 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.assessment.kpi.AbstractKPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import java.time.ZonedDateTime; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -26,7 +25,7 @@ public Map> getResults() { return results; } - public ZonedDateTime getDate() { + public LocalDateTime getDate() { return date; } } From a8b6691ff0109d7b04b2c1d6fe19ce7b0c4f3d5f Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 2 Aug 2021 15:42:00 +0200 Subject: [PATCH 143/310] Change LocalDatetime to ZonedDateTime --- .../schema/Models/LandscapeDescription.rst | 10 +-- docs/source/schema/spec.json | 70 +++++++++---------- .../bonndan/nivio/assessment/Assessment.java | 8 +-- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index 807ed451f..dd41a02f8 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -63,11 +63,6 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update - - optional, defaults to null - - null * - color - String - @@ -78,6 +73,11 @@ LandscapeDescription - - optional, defaults to null - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null * - items - List - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index cdef264f8..57ef7fb94 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -182,14 +182,14 @@ "example" : "shipping-mysqldb" } }, - "icon" : { - "type" : "string", - "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." + "icon": { + "type": "string", + "description": "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." }, - "color" : { - "type" : "string", - "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", - "example" : "4400FF" + "color": { + "type": "string", + "description": "Overrides the group color. Use an HTML hex color code without the leading hash.", + "example": "4400FF" }, "address": { "type": "string", @@ -239,12 +239,12 @@ "description": "A list of statuses that works like hardcoded KPIs." } }, - "frameworks" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "example" : "java: 8" + "frameworks": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "The parts used to create the item. Usually refers to technical frameworks.", + "example": "java: 8" }, "description" : "The parts used to create the item. Usually refers to technical frameworks.", "writeOnly" : true, @@ -282,15 +282,15 @@ "description": "Key of the label to evaluate", "example": "costs" }, - "messageTemplate" : { - "type" : "string", - "description" : "Template for the displayed message, containing a placeholder for the assessed value '%s", - "example" : "The current value is: %s" + "messageTemplate": { + "type": "string", + "description": "Template for the displayed message, containing a placeholder for the assessed value '%s", + "example": "The current value is: %s" }, - "ranges" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", + "ranges": { + "type": "object", + "additionalProperties": { + "type": "string", "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", "example" : "GREEN: 0;99.999999" }, @@ -399,13 +399,13 @@ "$ref" : "#/components/schemas/SourceReference" } }, - "config" : { - "$ref" : "#/components/schemas/LandscapeConfig" + "config": { + "$ref": "#/components/schemas/LandscapeConfig" }, - "groups" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/GroupDescription" + "groups": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/GroupDescription" }, "description": "Description of item groups (optional, can also be given in sources)." }, @@ -417,16 +417,16 @@ }, "description": "Additional labels for the landscape." }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" - }, "color": { "type": "string" }, "icon": { "type": "string" }, + "partial": { + "type": "boolean", + "description": "marks that the landscape is not complete, but an update" + }, "items": { "type": "array", "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", @@ -437,11 +437,11 @@ }, "links": { "type": "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" + "additionalProperties": { + "$ref": "#/components/schemas/Link" }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example": "github: https://github.com/dedica-team/nivio" } } }, diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessment.java b/src/main/java/de/bonndan/nivio/assessment/Assessment.java index 5ca6adffa..e5353cfc6 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessment.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessment.java @@ -2,7 +2,7 @@ import de.bonndan.nivio.assessment.kpi.AbstractKPI; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.List; import java.util.Map; @@ -14,10 +14,10 @@ public class Assessment { private final Map> results; - private final LocalDateTime date; + private final ZonedDateTime date; public Assessment(Map> results) { - date = LocalDateTime.now(); + date = ZonedDateTime.now(); this.results = results; } @@ -25,7 +25,7 @@ public Map> getResults() { return results; } - public LocalDateTime getDate() { + public ZonedDateTime getDate() { return date; } } From 0cb369f40286a3219f07877e7c32287d1de08625 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 3 Aug 2021 10:37:02 +0200 Subject: [PATCH 144/310] fix for schema generation --- docs/source/schema/Models/Branding.rst | 10 +- .../source/schema/Models/GroupDescription.rst | 50 +- .../schema/Models/InterfaceDescription.rst | 26 +- docs/source/schema/Models/ItemDescription.rst | 96 +-- docs/source/schema/Models/KPIConfig.rst | 20 +- docs/source/schema/Models/LandscapeConfig.rst | 28 +- .../schema/Models/LandscapeDescription.rst | 72 +-- docs/source/schema/Models/LayoutConfig.rst | 10 +- docs/source/schema/Models/Link.rst | 50 +- docs/source/schema/Models/SourceReference.rst | 66 +- docs/source/schema/spec.json | 591 +++++++++--------- .../bonndan/nivio/SchemaGenerationTest.java | 14 +- 12 files changed, 517 insertions(+), 516 deletions(-) diff --git a/docs/source/schema/Models/Branding.rst b/docs/source/schema/Models/Branding.rst index 277189d29..71e412368 100644 --- a/docs/source/schema/Models/Branding.rst +++ b/docs/source/schema/Models/Branding.rst @@ -13,14 +13,14 @@ Map branding (tweaks visuals) - Remarks - Example - * - mapStylesheet - - String - - A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map. - - optional, defaults to null - - https://acme.com/css/acme.css * - mapLogo - String - A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map. - optional, defaults to null - https://acme.com/images/logo.png + * - mapStylesheet + - String + - A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map. + - optional, defaults to null + - https://acme.com/css/acme.css diff --git a/docs/source/schema/Models/GroupDescription.rst b/docs/source/schema/Models/GroupDescription.rst index f81c1df1f..fb545e113 100644 --- a/docs/source/schema/Models/GroupDescription.rst +++ b/docs/source/schema/Models/GroupDescription.rst @@ -13,44 +13,34 @@ A group of items. Could be used as bounded context, for instance. - Remarks - Example - * - labels - - Map - - Labels related to the group. - - optional, defaults to null - - null - * - identifier - - String - - A unique identifier for the group (also used as name). Descriptions are merged based on the identifier. - - **required**, defaults to null - - shipping - * - owner - - String - - The business owner of the group. - - optional, defaults to null - - null - * - description + * - color - String - - A brief description. + - The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed. - optional, defaults to null - - null + - 05ffaa * - contact - String - A contact method, preferably email. - optional, defaults to null - null - * - color - - String - - The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed. - - optional, defaults to null - - 05ffaa * - contains - List - A list of item identifiers or SQL-like queries to easily assign items to this group. - optional, defaults to null - identifier LIKE 'DB1' - * - name + * - description - String - - + - A brief description. + - optional, defaults to null + - null + * - identifier + - String + - A unique identifier for the group (also used as name). Descriptions are merged based on the identifier. + - **required**, defaults to null + - shipping + * - labels + - Map + - Labels related to the group. - optional, defaults to null - null * - links @@ -58,4 +48,14 @@ A group of items. Could be used as bounded context, for instance. - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null - github: https://github.com/dedica-team/nivio + * - name + - String + - + - optional, defaults to null + - null + * - owner + - String + - The business owner of the group. + - optional, defaults to null + - null diff --git a/docs/source/schema/Models/InterfaceDescription.rst b/docs/source/schema/Models/InterfaceDescription.rst index 40fb7cbdc..5cc0fd2d8 100644 --- a/docs/source/schema/Models/InterfaceDescription.rst +++ b/docs/source/schema/Models/InterfaceDescription.rst @@ -13,6 +13,11 @@ Describes a low-level interface of an item. - Remarks - Example + * - deprecated + - Boolean + - + - optional, defaults to null + - null * - description - String - A brief description. @@ -23,22 +28,17 @@ Describes a low-level interface of an item. - The payload format. - optional, defaults to null - null - * - url + * - name - String - - A URL describing the endpoint. + - - optional, defaults to null - null - * - protection + * - parameters - String - - A description of the interface protection method. - - optional, defaults to null - - null - * - deprecated - - Boolean - - optional, defaults to null - null - * - name + * - path - String - - optional, defaults to null @@ -48,9 +48,9 @@ Describes a low-level interface of an item. - - optional, defaults to null - null - * - path + * - protection - String - - + - A description of the interface protection method. - optional, defaults to null - null * - summary @@ -58,9 +58,9 @@ Describes a low-level interface of an item. - - optional, defaults to null - null - * - parameters + * - url - String - - + - A URL describing the endpoint. - optional, defaults to null - null diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 022f72838..a724da709 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -13,24 +13,19 @@ List of configuration sources. Handled in the given order, latter extend/overwri - Remarks - Example - * - labels - - Map - - Key-value pair labels for an item. - - optional, defaults to null - - null - * - identifier + * - address - String - - Immutable unique identifier (maybe use an URN). Primary means to identify items in searches. - - **required**, defaults to null + - The technical address of the item (should be an URI). Taken into account when matching relation endpoints. + - optional, defaults to null - null - * - name + * - color - String - - A human readable name/title. The name is considered when items are searched. + - Overrides the group color. Use an HTML hex color code without the leading hash. - optional, defaults to null - - my beautiful service - * - owner + - 4400FF + * - contact - String - - The business owner of the item. Preferably use an email address. + - The primary way to contact a responsible person or team. Preferably use an email address. - optional, defaults to null - johnson@acme.com * - description @@ -38,74 +33,79 @@ List of configuration sources. Handled in the given order, latter extend/overwri - A brief description. - optional, defaults to null - null - * - contact - - String - - The primary way to contact a responsible person or team. Preferably use an email address. + * - frameworks + - Map + - The parts used to create the item. Usually refers to technical frameworks. - optional, defaults to null - - johnson@acme.com + - java: 8 * - group - String - The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common. - optional, defaults to null - shipping + * - icon + - String + - An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work). + - optional, defaults to null + - null + * - identifier + - String + - Immutable unique identifier (maybe use an URN). Primary means to identify items in searches. + - **required**, defaults to null + - null * - interfaces - Set - A collection of low level interfaces. Can be used to describe HTTP API endpoints for instance. - optional, defaults to null - null - * - providedBy - - List - - A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations. + * - labels + - Map + - Key-value pair labels for an item. - optional, defaults to null - - shipping-mysqldb - * - icon + - null + * - lifecycle - String - - An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work). + - The lifecycle state of an item. - optional, defaults to null - null - * - color - - String - - Overrides the group color. Use an HTML hex color code without the leading hash. + * - links + - Map + - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null - - 4400FF - * - address + - github: https://github.com/dedica-team/nivio + * - name - String - - The technical address of the item (should be an URI). Taken into account when matching relation endpoints. + - A human readable name/title. The name is considered when items are searched. - optional, defaults to null - - null - * - type + - my beautiful service + * - owner - String - - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. + - The business owner of the item. Preferably use an email address. - optional, defaults to null - - service|database|volume - * - lifecycle - - String - - The lifecycle state of an item. + - johnson@acme.com + * - providedBy + - List + - A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations. - optional, defaults to null - - null - * - statuses + - shipping-mysqldb + * - status - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - status + * - statuses - List - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - frameworks - - Map - - The parts used to create the item. Usually refers to technical frameworks. - - optional, defaults to null - - java: 8 * - tags - List - - optional, defaults to null - null - * - links - - Map - - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. + * - type + - String + - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. - optional, defaults to null - - github: https://github.com/dedica-team/nivio + - service|database|volume diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index e170f09ad..64309854b 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -18,11 +18,21 @@ The configuration of landscape specific key performance indicators that derive s - Description of the purpose of the KPI - optional, defaults to null - null + * - enabled + - Boolean + - A flag indicating that the KPI is active. Can be used to disable default kpis. + - optional, defaults to null + - null * - label - String - Key of the label to evaluate - **required**, defaults to null - costs + * - matches + - Map + - A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers. + - optional, defaults to null + - RED: BAD;err.* * - messageTemplate - String - Template for the displayed message, containing a placeholder for the assessed value '%s @@ -33,14 +43,4 @@ The configuration of landscape specific key performance indicators that derive s - A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers. - optional, defaults to null - GREEN: 0;99.999999 - * - matches - - Map - - A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers. - - optional, defaults to null - - RED: BAD;err.* - * - enabled - - Boolean - - A flag indicating that the KPI is active. Can be used to disable default kpis. - - optional, defaults to null - - null diff --git a/docs/source/schema/Models/LandscapeConfig.rst b/docs/source/schema/Models/LandscapeConfig.rst index d52a9e346..8a34baab4 100644 --- a/docs/source/schema/Models/LandscapeConfig.rst +++ b/docs/source/schema/Models/LandscapeConfig.rst @@ -13,11 +13,21 @@ Configuration of key performance indicators (i.e. status indicators) and layouti - Remarks - Example + * - branding + - Branding + - + - optional, defaults to null + - null * - greedy - Boolean - Flag that enables instant creation items based relation targets that cannot be found in the sources. - optional, defaults to null - null + * - groupBlacklist + - List + - Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results. + - optional, defaults to null + - .*infra.* * - groupLayoutConfig - LayoutConfig - @@ -28,24 +38,14 @@ Configuration of key performance indicators (i.e. status indicators) and layouti - - optional, defaults to null - null - * - groupBlacklist - - List - - Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results. + * - kpis + - Map + - Key performance indicator configs. Each KPI must have a unique identifier. - optional, defaults to null - - .*infra.* + - null * - labelBlacklist - List - Names or patterns of labels that should be ignored. Used to improve automatic scanning results. - optional, defaults to null - .*COMPOSITION.* - * - branding - - Branding - - - - optional, defaults to null - - null - * - kpis - - Map - - Key performance indicator configs. Each KPI must have a unique identifier. - - optional, defaults to null - - null diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index dd41a02f8..8ce2afd12 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -13,15 +13,15 @@ LandscapeDescription - Remarks - Example - * - identifier + * - color - String - - Immutable unique identifier. Maybe use an URN. - - **required**, defaults to null + - + - optional, defaults to null - null - * - name - - String - - Human readable name. - - **required**, defaults to null + * - config + - LandscapeConfig + - + - optional, defaults to null - null * - contact - String @@ -33,29 +33,24 @@ LandscapeDescription - A brief description of the landscape. - optional, defaults to null - null - * - owner - - String - - The business owner (person or team), preferably an email address. - - optional, defaults to null - - null - * - templates - - Map - - Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items. + * - groups + - Map + - Description of item groups (optional, can also be given in sources). - optional, defaults to null - null - * - sources - - List + * - icon + - String - - optional, defaults to null - null - * - config - - LandscapeConfig - - - - optional, defaults to null + * - identifier + - String + - Immutable unique identifier. Maybe use an URN. + - **required**, defaults to null - null - * - groups - - Map - - Description of item groups (optional, can also be given in sources). + * - items + - List + - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null * - labels @@ -63,14 +58,19 @@ LandscapeDescription - Additional labels for the landscape. - optional, defaults to null - null - * - color - - String - - + * - links + - Map + - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null + - github: https://github.com/dedica-team/nivio + * - name + - String + - Human readable name. + - **required**, defaults to null - null - * - icon + * - owner - String - - + - The business owner (person or team), preferably an email address. - optional, defaults to null - null * - partial @@ -78,14 +78,14 @@ LandscapeDescription - marks that the landscape is not complete, but an update - optional, defaults to null - null - * - items - - List - - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. + * - sources + - List + - - optional, defaults to null - null - * - links - - Map - - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. + * - templates + - Map + - Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items. - optional, defaults to null - - github: https://github.com/dedica-team/nivio + - null diff --git a/docs/source/schema/Models/LayoutConfig.rst b/docs/source/schema/Models/LayoutConfig.rst index 843ee8bb8..51461cf3d 100644 --- a/docs/source/schema/Models/LayoutConfig.rst +++ b/docs/source/schema/Models/LayoutConfig.rst @@ -13,11 +13,6 @@ Layout configuration. See https://jgraph.github.io/mxgraph/java/docs/com/mxgraph - Remarks - Example - * - maxIterations - - Integer - - The maximum number of iterations. More iterations theoretically lead to better results. - - optional, defaults to null - - null * - forceConstantFactor - Float - A factor to influence the attracting and repulsive forces in a layout. @@ -28,6 +23,11 @@ Layout configuration. See https://jgraph.github.io/mxgraph/java/docs/com/mxgraph - A factor to influence maximum distance where forces are applied. - optional, defaults to null - null + * - maxIterations + - Integer + - The maximum number of iterations. More iterations theoretically lead to better results. + - optional, defaults to null + - null * - minDistanceLimitFactor - Float - A factor to influence minimum distance where forces are applied. diff --git a/docs/source/schema/Models/Link.rst b/docs/source/schema/Models/Link.rst index dad30c0bd..661f826ec 100644 --- a/docs/source/schema/Models/Link.rst +++ b/docs/source/schema/Models/Link.rst @@ -13,62 +13,62 @@ A link to an external resource. Contains a href (URL) plus various attributes fo - Remarks - Example - * - rel + * - basicAuthPassword - String - - hateoas relation type + - - optional, defaults to null - null - * - href - - String - - The link target. - - **required**, defaults to null - - null - * - hreflang + * - basicAuthUsername - String - - hateoas language + - - optional, defaults to null - null - * - media + * - deprecation - String - - hateoas media type + - deprecation info (typically used in OpenAPI specs) - optional, defaults to null - null - * - title + * - headerTokenName - String - - hateoas title + - - optional, defaults to null - null - * - type + * - headerTokenValue - String - - optional, defaults to null - null - * - deprecation + * - href - String - - deprecation info (typically used in OpenAPI specs) + - The link target. + - **required**, defaults to null + - null + * - hreflang + - String + - hateoas language - optional, defaults to null - null - * - name + * - media - String - - HateOAS / OpenAPI name + - hateoas media type - optional, defaults to null - null - * - basicAuthUsername + * - name - String - - + - HateOAS / OpenAPI name - optional, defaults to null - null - * - basicAuthPassword + * - rel - String - - + - hateoas relation type - optional, defaults to null - null - * - headerTokenName + * - title - String - - + - hateoas title - optional, defaults to null - null - * - headerTokenValue + * - type - String - - optional, defaults to null diff --git a/docs/source/schema/Models/SourceReference.rst b/docs/source/schema/Models/SourceReference.rst index f406e9dae..edafa9c71 100644 --- a/docs/source/schema/Models/SourceReference.rst +++ b/docs/source/schema/Models/SourceReference.rst @@ -13,62 +13,72 @@ This is a reference to a configuration file. - Remarks - Example - * - rel + * - assignTemplates + - Map + - A map with template identifier as key and item identifier matchers as value + - optional, defaults to null + - endOfLife: [web, "java6*"] + * - basicAuthPassword - String - - hateoas relation type + - - optional, defaults to null - null - * - href + * - basicAuthUsername - String - - The link target. - - **required**, defaults to null + - + - optional, defaults to null - null - * - hreflang + * - deprecation - String - - hateoas language + - deprecation info (typically used in OpenAPI specs) - optional, defaults to null - null - * - media + * - format - String - - hateoas media type + - The input format. - optional, defaults to null - null - * - title + * - headerTokenName - String - - hateoas title + - - optional, defaults to null - null - * - type + * - headerTokenValue - String - - optional, defaults to null - null - * - deprecation + * - href - String - - deprecation info (typically used in OpenAPI specs) + - The link target. + - **required**, defaults to null + - null + * - hreflang + - String + - hateoas language - optional, defaults to null - null - * - name + * - media - String - - HateOAS / OpenAPI name + - hateoas media type - optional, defaults to null - null - * - basicAuthUsername + * - name - String - - + - HateOAS / OpenAPI name - optional, defaults to null - null - * - basicAuthPassword + * - rel - String - - + - hateoas relation type - optional, defaults to null - null - * - headerTokenName + * - title - String - - + - hateoas title - optional, defaults to null - null - * - headerTokenValue + * - type - String - - optional, defaults to null @@ -78,14 +88,4 @@ This is a reference to a configuration file. - A URL, but can also be a relative path. - optional, defaults to null - ./a/items.yaml - * - format - - String - - The input format. - - optional, defaults to null - - null - * - assignTemplates - - Map - - A map with template identifier as key and item identifier matchers as value - - optional, defaults to null - - endOfLife: [web, "java6*"] diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 57ef7fb94..5228cc83e 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -11,15 +11,15 @@ "Branding" : { "type" : "object", "properties" : { - "mapStylesheet" : { - "type" : "string", - "description" : "A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map.", - "example" : "https://acme.com/css/acme.css" - }, "mapLogo" : { "type" : "string", "description" : "A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map.", "example" : "https://acme.com/images/logo.png" + }, + "mapStylesheet" : { + "type" : "string", + "description" : "A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map.", + "example" : "https://acme.com/css/acme.css" } }, "description" : "Map branding (tweaks visuals)" @@ -28,36 +28,15 @@ "required" : [ "identifier" ], "type" : "object", "properties" : { - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Labels related to the group." - }, - "description" : "Labels related to the group." - }, - "identifier" : { - "type" : "string", - "description" : "A unique identifier for the group (also used as name). Descriptions are merged based on the identifier.", - "example" : "shipping" - }, - "owner" : { - "type" : "string", - "description" : "The business owner of the group." - }, - "description" : { + "color" : { "type" : "string", - "description" : "A brief description." + "description" : "The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed.", + "example" : "05ffaa" }, "contact" : { "type" : "string", "description" : "A contact method, preferably email." }, - "color" : { - "type" : "string", - "description" : "The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed.", - "example" : "05ffaa" - }, "contains" : { "type" : "array", "description" : "A list of item identifiers or SQL-like queries to easily assign items to this group.", @@ -68,8 +47,22 @@ "example" : "identifier LIKE 'DB1'" } }, - "name" : { - "type" : "string" + "description" : { + "type" : "string", + "description" : "A brief description." + }, + "identifier" : { + "type" : "string", + "description" : "A unique identifier for the group (also used as name). Descriptions are merged based on the identifier.", + "example" : "shipping" + }, + "labels" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "Labels related to the group." + }, + "description" : "Labels related to the group." }, "links" : { "type" : "object", @@ -78,6 +71,13 @@ }, "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", "example" : "github: https://github.com/dedica-team/nivio" + }, + "name" : { + "type" : "string" + }, + "owner" : { + "type" : "string", + "description" : "The business owner of the group." } }, "description" : "A group of items. Could be used as bounded context, for instance." @@ -85,6 +85,9 @@ "InterfaceDescription" : { "type" : "object", "properties" : { + "deprecated" : { + "type" : "boolean" + }, "description" : { "type" : "string", "description" : "A brief description." @@ -93,32 +96,29 @@ "type" : "string", "description" : "The payload format." }, - "url" : { - "type" : "string", - "description" : "A URL describing the endpoint.", - "format" : "url" - }, - "protection" : { - "type" : "string", - "description" : "A description of the interface protection method." - }, - "deprecated" : { - "type" : "boolean" - }, "name" : { "type" : "string" }, - "payload" : { + "parameters" : { "type" : "string" }, "path" : { "type" : "string" }, - "summary" : { + "payload" : { "type" : "string" }, - "parameters" : { + "protection" : { + "type" : "string", + "description" : "A description of the interface protection method." + }, + "summary" : { "type" : "string" + }, + "url" : { + "type" : "string", + "description" : "A URL describing the endpoint.", + "format" : "url" } }, "description" : "Describes a low-level interface of an item." @@ -127,43 +127,49 @@ "required" : [ "identifier" ], "type" : "object", "properties" : { - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Key-value pair labels for an item." - }, - "description" : "Key-value pair labels for an item." - }, - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "address" : { "type" : "string", - "description" : "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." + "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." }, - "name" : { + "color" : { "type" : "string", - "description" : "A human readable name/title. The name is considered when items are searched.", - "example" : "my beautiful service" + "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", + "example" : "4400FF" }, - "owner" : { + "contact" : { "type" : "string", - "description" : "The business owner of the item. Preferably use an email address.", + "description" : "The primary way to contact a responsible person or team. Preferably use an email address.", "example" : "johnson@acme.com" }, "description" : { "type" : "string", "description" : "A brief description." }, - "contact" : { - "type" : "string", - "description" : "The primary way to contact a responsible person or team. Preferably use an email address.", - "example" : "johnson@acme.com" + "frameworks" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "example" : "java: 8" + }, + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "writeOnly" : true, + "example" : "java: 8" }, "group" : { "type" : "string", "description" : "The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common.", "example" : "shipping" }, + "icon" : { + "type" : "string", + "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." + }, + "identifier" : { + "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type" : "string", + "description" : "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." + }, "interfaces" : { "uniqueItems" : true, "type" : "array", @@ -172,6 +178,38 @@ "$ref" : "#/components/schemas/InterfaceDescription" } }, + "labels" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "Key-value pair labels for an item." + }, + "description" : "Key-value pair labels for an item." + }, + "lifecycle" : { + "type" : "string", + "description" : "The lifecycle state of an item.", + "writeOnly" : true, + "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] + }, + "links" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/Link" + }, + "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example" : "github: https://github.com/dedica-team/nivio" + }, + "name" : { + "type" : "string", + "description" : "A human readable name/title. The name is considered when items are searched.", + "example" : "my beautiful service" + }, + "owner" : { + "type" : "string", + "description" : "The business owner of the item. Preferably use an email address.", + "example" : "johnson@acme.com" + }, "providedBy" : { "type" : "array", "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", @@ -182,120 +220,62 @@ "example" : "shipping-mysqldb" } }, - "icon": { - "type": "string", - "description": "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." - }, - "color": { - "type": "string", - "description": "Overrides the group color. Use an HTML hex color code without the leading hash.", - "example": "4400FF" - }, - "address": { - "type": "string", - "description": "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." - }, - "type": { - "type": "string", - "description": "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - "example": "service|database|volume" - }, - "lifecycle": { - "type": "string", - "description": "The lifecycle state of an item.", - "writeOnly": true, - "enum": [ - "PLANNED", - "INTEGRATION", - "TEST", - "PRODUCTION", - "END_OF_LIFE", - "EOL" - ] - }, - "statuses": { - "type": "array", - "description": "A list of statuses that works like hardcoded KPIs.", - "writeOnly": true, - "items": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A list of statuses that works like hardcoded KPIs." + "status" : { + "type" : "array", + "description" : "A list of statuses that works like hardcoded KPIs.", + "writeOnly" : true, + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A list of statuses that works like hardcoded KPIs." }, - "description": "A list of statuses that works like hardcoded KPIs." + "description" : "A list of statuses that works like hardcoded KPIs." } }, - "status": { - "type": "array", - "description": "A list of statuses that works like hardcoded KPIs.", - "writeOnly": true, - "items": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A list of statuses that works like hardcoded KPIs." + "statuses" : { + "type" : "array", + "description" : "A list of statuses that works like hardcoded KPIs.", + "writeOnly" : true, + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A list of statuses that works like hardcoded KPIs." }, - "description": "A list of statuses that works like hardcoded KPIs." + "description" : "A list of statuses that works like hardcoded KPIs." } }, - "frameworks": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "The parts used to create the item. Usually refers to technical frameworks.", - "example": "java: 8" - }, - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "writeOnly" : true, - "example" : "java: 8" - }, "tags" : { "type" : "array", "items" : { "type" : "string" } }, - "links" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" - }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "type" : { + "type" : "string", + "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", + "example" : "service|database|volume" } }, "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." }, "KPIConfig" : { - "required": [ - "label" - ], - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Description of the purpose of the KPI" - }, - "label": { - "type": "string", - "description": "Key of the label to evaluate", - "example": "costs" - }, - "messageTemplate": { - "type": "string", - "description": "Template for the displayed message, containing a placeholder for the assessed value '%s", - "example": "The current value is: %s" - }, - "ranges": { - "type": "object", - "additionalProperties": { - "type": "string", - "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", - "example" : "GREEN: 0;99.999999" - }, - "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", - "example" : "GREEN: 0;99.999999" + "required" : [ "label" ], + "type" : "object", + "properties" : { + "description" : { + "type" : "string", + "description" : "Description of the purpose of the KPI" + }, + "enabled" : { + "type" : "boolean", + "description" : "A flag indicating that the KPI is active. Can be used to disable default kpis." + }, + "label" : { + "type" : "string", + "description" : "Key of the label to evaluate", + "example" : "costs" }, "matches" : { "type" : "object", @@ -307,9 +287,20 @@ "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", "example" : "RED: BAD;err.*" }, - "enabled" : { - "type" : "boolean", - "description" : "A flag indicating that the KPI is active. Can be used to disable default kpis." + "messageTemplate" : { + "type" : "string", + "description" : "Template for the displayed message, containing a placeholder for the assessed value '%s", + "example" : "The current value is: %s" + }, + "ranges" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", + "example" : "GREEN: 0;99.999999" + }, + "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", + "example" : "GREEN: 0;99.999999" } }, "description" : "The configuration of landscape specific key performance indicators that derive status information from landscape components. Usually the KPIs work on labels" @@ -317,16 +308,13 @@ "LandscapeConfig" : { "type" : "object", "properties" : { + "branding" : { + "$ref" : "#/components/schemas/Branding" + }, "greedy" : { "type" : "boolean", "description" : "Flag that enables instant creation items based relation targets that cannot be found in the sources." }, - "groupLayoutConfig" : { - "$ref" : "#/components/schemas/LayoutConfig" - }, - "itemLayoutConfig" : { - "$ref" : "#/components/schemas/LayoutConfig" - }, "groupBlacklist" : { "type" : "array", "description" : "Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results.", @@ -337,6 +325,19 @@ "example" : ".*infra.*" } }, + "groupLayoutConfig" : { + "$ref" : "#/components/schemas/LayoutConfig" + }, + "itemLayoutConfig" : { + "$ref" : "#/components/schemas/LayoutConfig" + }, + "kpis" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/KPIConfig" + }, + "description" : "Key performance indicator configs. Each KPI must have a unique identifier." + }, "labelBlacklist" : { "type" : "array", "description" : "Names or patterns of labels that should be ignored. Used to improve automatic scanning results.", @@ -346,16 +347,6 @@ "description" : "Names or patterns of labels that should be ignored. Used to improve automatic scanning results.", "example" : ".*COMPOSITION.*" } - }, - "branding" : { - "$ref" : "#/components/schemas/Branding" - }, - "kpis" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/KPIConfig" - }, - "description" : "Key performance indicator configs. Each KPI must have a unique identifier." } }, "description" : "Configuration of key performance indicators (i.e. status indicators) and layouting tweaks." @@ -364,14 +355,11 @@ "required" : [ "identifier", "name" ], "type" : "object", "properties" : { - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", - "type" : "string", - "description" : "Immutable unique identifier. Maybe use an URN." + "color" : { + "type" : "string" }, - "name" : { - "type" : "string", - "description" : "Human readable name." + "config" : { + "$ref" : "#/components/schemas/LandscapeConfig" }, "contact" : { "type" : "string", @@ -381,78 +369,76 @@ "type" : "string", "description" : "A brief description of the landscape." }, - "owner" : { - "type" : "string", - "description" : "The business owner (person or team), preferably an email address." - }, - "templates" : { + "groups" : { "type" : "object", "additionalProperties" : { - "$ref" : "#/components/schemas/ItemDescription" + "$ref" : "#/components/schemas/GroupDescription" }, - "description" : "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." + "description" : "Description of item groups (optional, can also be given in sources)." }, - "sources" : { + "icon" : { + "type" : "string" + }, + "identifier" : { + "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type" : "string", + "description" : "Immutable unique identifier. Maybe use an URN." + }, + "items" : { "type" : "array", + "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", "writeOnly" : true, "items" : { - "$ref" : "#/components/schemas/SourceReference" + "$ref" : "#/components/schemas/ItemDescription" } }, - "config": { - "$ref": "#/components/schemas/LandscapeConfig" - }, - "groups": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/GroupDescription" + "labels" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "Additional labels for the landscape." }, - "description": "Description of item groups (optional, can also be given in sources)." + "description" : "Additional labels for the landscape." }, - "labels": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "Additional labels for the landscape." + "links" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/Link" }, - "description": "Additional labels for the landscape." + "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example" : "github: https://github.com/dedica-team/nivio" }, - "color": { - "type": "string" + "name" : { + "type" : "string", + "description" : "Human readable name." }, - "icon": { - "type": "string" + "owner" : { + "type" : "string", + "description" : "The business owner (person or team), preferably an email address." }, - "partial": { - "type": "boolean", - "description": "marks that the landscape is not complete, but an update" + "partial" : { + "type" : "boolean", + "description" : "marks that the landscape is not complete, but an update" }, - "items": { - "type": "array", - "description": "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly": true, - "items": { - "$ref": "#/components/schemas/ItemDescription" + "sources" : { + "type" : "array", + "writeOnly" : true, + "items" : { + "$ref" : "#/components/schemas/SourceReference" } }, - "links": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/Link" + "templates" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/ItemDescription" }, - "description": "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example": "github: https://github.com/dedica-team/nivio" + "description" : "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." } } }, "LayoutConfig" : { "type" : "object", "properties" : { - "maxIterations" : { - "type" : "integer", - "description" : "The maximum number of iterations. More iterations theoretically lead to better results.", - "format" : "int32" - }, "forceConstantFactor" : { "type" : "number", "description" : "A factor to influence the attracting and repulsive forces in a layout.", @@ -463,6 +449,11 @@ "description" : "A factor to influence maximum distance where forces are applied.", "format" : "float" }, + "maxIterations" : { + "type" : "integer", + "description" : "The maximum number of iterations. More iterations theoretically lead to better results.", + "format" : "int32" + }, "minDistanceLimitFactor" : { "type" : "number", "description" : "A factor to influence minimum distance where forces are applied.", @@ -475,9 +466,25 @@ "required" : [ "href" ], "type" : "object", "properties" : { - "rel" : { + "basicAuthPassword" : { "type" : "string", - "description" : "hateoas relation type" + "writeOnly" : true + }, + "basicAuthUsername" : { + "type" : "string", + "writeOnly" : true + }, + "deprecation" : { + "type" : "string", + "description" : "deprecation info (typically used in OpenAPI specs)" + }, + "headerTokenName" : { + "type" : "string", + "writeOnly" : true + }, + "headerTokenValue" : { + "type" : "string", + "writeOnly" : true }, "href" : { "type" : "string", @@ -492,28 +499,60 @@ "type" : "string", "description" : "hateoas media type" }, + "name" : { + "type" : "string", + "description" : "HateOAS / OpenAPI name" + }, + "rel" : { + "type" : "string", + "description" : "hateoas relation type" + }, "title" : { "type" : "string", "description" : "hateoas title" }, "type" : { "type" : "string" + } + }, + "description" : "A link to an external resource. Contains a href (URL) plus various attributes for authentication and/or hateoas.", + "example" : "github: https://github.com/dedica-team/nivio" + }, + "SourceReference" : { + "required" : [ "href" ], + "type" : "object", + "properties" : { + "assignTemplates" : { + "type" : "object", + "additionalProperties" : { + "type" : "array", + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]", + "items" : { + "type" : "string", + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]" + } + }, + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]" }, - "deprecation" : { - "type" : "string", - "description" : "deprecation info (typically used in OpenAPI specs)" - }, - "name" : { + "basicAuthPassword" : { "type" : "string", - "description" : "HateOAS / OpenAPI name" + "writeOnly" : true }, "basicAuthUsername" : { "type" : "string", "writeOnly" : true }, - "basicAuthPassword" : { + "deprecation" : { "type" : "string", - "writeOnly" : true + "description" : "deprecation info (typically used in OpenAPI specs)" + }, + "format" : { + "type" : "string", + "description" : "The input format.", + "enum" : [ "nivio", "csv", "k8s", "rancher", "docker-compose-v2" ] }, "headerTokenName" : { "type" : "string", @@ -522,18 +561,6 @@ "headerTokenValue" : { "type" : "string", "writeOnly" : true - } - }, - "description" : "A link to an external resource. Contains a href (URL) plus various attributes for authentication and/or hateoas.", - "example" : "github: https://github.com/dedica-team/nivio" - }, - "SourceReference" : { - "required" : [ "href" ], - "type" : "object", - "properties" : { - "rel" : { - "type" : "string", - "description" : "hateoas relation type" }, "href" : { "type" : "string", @@ -548,61 +575,25 @@ "type" : "string", "description" : "hateoas media type" }, - "title" : { - "type" : "string", - "description" : "hateoas title" - }, - "type" : { - "type" : "string" - }, - "deprecation" : { - "type" : "string", - "description" : "deprecation info (typically used in OpenAPI specs)" - }, "name" : { "type" : "string", "description" : "HateOAS / OpenAPI name" }, - "basicAuthUsername" : { - "type" : "string", - "writeOnly" : true - }, - "basicAuthPassword" : { + "rel" : { "type" : "string", - "writeOnly" : true + "description" : "hateoas relation type" }, - "headerTokenName" : { + "title" : { "type" : "string", - "writeOnly" : true + "description" : "hateoas title" }, - "headerTokenValue" : { - "type" : "string", - "writeOnly" : true + "type" : { + "type" : "string" }, "url" : { "type" : "string", "description" : "A URL, but can also be a relative path.", "example" : "./a/items.yaml" - }, - "format" : { - "type" : "string", - "description" : "The input format.", - "enum" : [ "nivio", "csv", "k8s", "rancher", "docker-compose-v2" ] - }, - "assignTemplates" : { - "type" : "object", - "additionalProperties" : { - "type" : "array", - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]", - "items" : { - "type" : "string", - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]" - } - }, - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]" } }, "description" : "This is a reference to a configuration file." diff --git a/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java b/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java index 301f07bd1..47f4c1bc0 100644 --- a/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java +++ b/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java @@ -19,14 +19,14 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Map; +import java.util.TreeMap; public class SchemaGenerationTest { @Test void generateDocs() { Components components = new Components(); - Map schema = ModelConverters.getInstance().readAll(new AnnotatedType(LandscapeDescription.class)); - components.setSchemas(schema); + components.setSchemas(getSchemaMap()); OpenAPI openAPI = new OpenAPI(); openAPI.setComponents(components); openAPI.setPaths(new Paths()); @@ -55,4 +55,14 @@ void generateDocs() { defaultGenerator.opts(config); defaultGenerator.generate(); } + + @SuppressWarnings("rawtypes") + private Map getSchemaMap() { + Map stringSchemaMap = ModelConverters.getInstance().readAll(new AnnotatedType(LandscapeDescription.class)); + stringSchemaMap.keySet().forEach(s -> { + Schema schema = stringSchemaMap.get(s); + schema.setProperties(new TreeMap(schema.getProperties())); + }); + return stringSchemaMap; + } } From de6e681095f9ce23279f732830007b4447e69129 Mon Sep 17 00:00:00 2001 From: robert Date: Tue, 3 Aug 2021 13:31:01 +0200 Subject: [PATCH 145/310] Merge develop into feature branch --- .../nivio/assessment/kpi/KubernetesKPI.java | 9 +- .../java/de/bonndan/nivio/input/Seed.java | 2 +- .../InputFormatHandlerKubernetes.java | 2 +- .../java/de/bonndan/nivio/model/Label.java | 2 +- .../assessment/kpi/KubernetesKpiTest.java | 88 ++++++++++--------- 5 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index 54994be6b..fc5e8a937 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -1,8 +1,8 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; import org.apache.commons.collections.map.SingletonMap; @@ -22,14 +22,14 @@ public class KubernetesKPI implements KPI { @Override @NonNull - public List getStatusValues(Component component) { - if (!(component instanceof Labeled)) + public List getStatusValues(Assessable assessable) { + if (!(assessable instanceof Labeled)) return new ArrayList<>(); var statusList = new ArrayList(); var counter = new AtomicInteger(0); - ((Labeled) component).getLabels(Label.k8s).forEach((key, value) -> { + ((Labeled) assessable).getLabels(Label.k8s).forEach((key, value) -> { if (ObjectUtils.isEmpty(value)) { return; } @@ -50,7 +50,6 @@ public List getStatusValues(Component component) { statusList.add(statusValue); }); return statusList; - } private Integer getIntegerValue(String[] splitValue, int position) { diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index cadc889b2..63f0884c4 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -70,7 +70,7 @@ public List getDemoFiles() { Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { - demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); + demoFiles.add(new File(absPath + "/src/test/resources/example/example_k8s.yml").toURI().toURL()); if (value.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index 17dce5fa3..b56dd28fd 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -113,7 +113,7 @@ private List createItemDescription(List itemList) { itemDescription.setOwner(item.getOwner().get(0).getName()); } itemDescription.setGroup(item.getGroup()); - item.getOwner().forEach(owner -> itemDescription.addRelation(new RelationDescription(owner.getUid(), item.getUid()))); + item.getOwner().forEach(owner -> itemDescription.addOrReplaceRelation(new RelationDescription(owner.getUid(), item.getUid()))); if (!item.getDetails().isEmpty()) { item.getDetails().forEach(itemDescription::setLabel); } diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 0699a02c3..7cfe999bd 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -58,7 +58,7 @@ public enum Label { condition("Prefix for condition labels.", true), - weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."); + weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."), k8s("Prefix for k8s labels.", true); diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java index 8382ecf44..6243cc854 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java @@ -1,13 +1,15 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.input.dto.ItemDescription; -import de.bonndan.nivio.model.Component; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Landscape; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -21,50 +23,50 @@ void setUp() { @Test void getStatusValues() { - assertThat(kubernetesKPI.getStatusValues(Mockito.mock(Component.class)).getClass()).isEqualTo(ArrayList.class); - var itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.boolcondition.test", "true"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("test"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.boolcondition.test", "false"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.RED); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("test"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + assertThat(kubernetesKPI.getStatusValues(Mockito.mock(Assessable.class)).getClass()).isEqualTo(ArrayList.class); + var item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.boolcondition.test", "true"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.boolcondition.test", "false"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.replicacondition.test", "a;1"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.ORANGE); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("ReadyReplicas count was null"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.replicacondition.test", "1;a"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.ORANGE); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("Replicas count was null"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.replicacondition.test", "a;1"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("ReadyReplicas count was null"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.replicacondition.test", "1;a"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("Replicas count was null"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.replicacondition.test", "2;2"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("all pods are ready"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.replicacondition.test", "1;2"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.YELLOW); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("1 of 2 Pods are ready"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.replicacondition.test", "0;2"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.RED); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("0 of 2 Pods are ready"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.replicacondition.test", "2;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("all pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.replicacondition.test", "1;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.YELLOW); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("1 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.replicacondition.test", "0;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("0 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); - itemDescription = new ItemDescription(); - itemDescription.setLabel("k8s.testcondition.test", Status.GREEN.toString()); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getStatus()).isEqualTo(Status.GREEN); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getMessage()).isEqualTo("testcondition.test"); - assertThat(kubernetesKPI.getStatusValues(itemDescription).get(0).getField()).isEqualTo("k8s:0"); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null); + item.setLabel("k8s.testcondition.test", Status.GREEN.toString()); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("testcondition.test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); } @Test From 45b51d63a965d88720f195be78436327f8da5de7 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Tue, 3 Aug 2021 20:18:26 +0200 Subject: [PATCH 146/310] fix demo landscape --- src/main/java/de/bonndan/nivio/input/Seed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index 63f0884c4..cadc889b2 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -70,7 +70,7 @@ public List getDemoFiles() { Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { - demoFiles.add(new File(absPath + "/src/test/resources/example/example_k8s.yml").toURI().toURL()); + demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); if (value.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); From 6d02278d634093cb3ce54d1db9e454ec140134c0 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Wed, 4 Aug 2021 17:01:21 +0200 Subject: [PATCH 147/310] [#635] NPE fix / fix method call --- .../de/bonndan/nivio/output/docs/HtmlGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java index 831a5f968..521744670 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java @@ -16,10 +16,7 @@ import org.springframework.util.StringUtils; import java.net.URL; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -86,7 +83,10 @@ protected ContainerTag writeItem(Item item, Assessment assessment, Collection String.format("%s: %s", StringUtils.capitalize(Label.framework.unprefixed(mapEntry.getKey())), mapEntry.getValue())) .collect(Collectors.toList()); - List statusValues = assessment.getResults().get(item.getFullyQualifiedIdentifier()); + List statusValues = assessment.getResults().get(item.getAssessmentIdentifier()); + if (statusValues == null) { + statusValues = new ArrayList<>(); + } return div( div( From 2e33f7cf5f458b93fcbf8769b5a46dd3539c822e Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 6 Aug 2021 10:28:03 +0200 Subject: [PATCH 148/310] Add KubernetesObserver --- .../InputFormatHandlerKubernetes.java | 8 ++++--- .../input/kubernetes/KubernetesObserver.java | 22 +++++++++++++------ .../status/KubernetesObserverRegistry.java | 14 +++++------- .../nivio/observation/ObserverRegistry.java | 7 ------ .../InputFormatHandlerKubernetesTest.java | 3 ++- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index b56dd28fd..dd3746780 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -7,6 +7,7 @@ import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; +import de.bonndan.nivio.model.LandscapeRepository; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.client.Config; @@ -16,6 +17,7 @@ import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.lang.NonNull; import java.net.URL; @@ -36,10 +38,11 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { public static final String LABEL_PREFIX = "k8s."; + private LandscapeRepository landscapeRepository; private KubernetesClient client; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - public InputFormatHandlerKubernetes(Optional client) { + public InputFormatHandlerKubernetes(Optional client, LandscapeRepository landscapeRepository) { this.client = client.orElse(null); } @@ -53,7 +56,6 @@ public List getFormats() { */ @Override public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { - this.client = getClient(reference.getUrl()); try { @@ -170,7 +172,7 @@ private void crossReferenceService(List service, List owners) @Override public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference) { - return null; + return new KubernetesObserver(landscapeRepository.findDistinctByIdentifier(sourceReference.getLandscapeDescription().getIdentifier()), new StaticApplicationContext(), this.client); } private KubernetesClient getClient(String context) { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java index 594099783..6cf593d2f 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java @@ -1,8 +1,10 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.IndexEvent; -import de.bonndan.nivio.input.dto.LandscapeDescription; + +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.observation.InputChangedEvent; import de.bonndan.nivio.observation.InputFormatObserver; +import de.bonndan.nivio.observation.ObservedChange; import io.fabric8.kubernetes.api.model.events.v1.Event; import io.fabric8.kubernetes.client.KubernetesClient; import org.slf4j.Logger; @@ -11,6 +13,7 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @@ -18,13 +21,13 @@ public class KubernetesObserver implements InputFormatObserver { private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesObserver.class); - private final LandscapeDescription landscapeDescription; + private final Landscape landscape; private final ApplicationEventPublisher eventPublisher; private final KubernetesClient kubernetesClient; private List eventList = null; - public KubernetesObserver(@NonNull final LandscapeDescription landscapeDescription, @NonNull final ApplicationEventPublisher eventPublisher, @NonNull final KubernetesClient kubernetesClient) { - this.landscapeDescription = landscapeDescription; + public KubernetesObserver(@NonNull final Optional landscape, @NonNull final ApplicationEventPublisher eventPublisher, @NonNull final KubernetesClient kubernetesClient) { + this.landscape = landscape.get(); this.kubernetesClient = kubernetesClient; this.eventPublisher = eventPublisher; } @@ -32,10 +35,15 @@ public KubernetesObserver(@NonNull final LandscapeDescription landscapeDescripti @Override public void run() { while (true) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } if (eventList == null) { eventList = kubernetesClient.events().v1().events().list().getItems(); } else { - if (compareEvents(eventList, kubernetesClient.events().v1().events().list().getItems())) { + if (!compareEvents(eventList, kubernetesClient.events().v1().events().list().getItems())) { triggerChange(); return; } @@ -51,6 +59,6 @@ private boolean compareEvents(@NonNull List eventListOld, @NonNull List { LOGGER.info("Registered landscape {} for observation.", landscapeDescription); return new LandscapeObserverPool(taskScheduler, 30 * 1000); }); - pool.updateObservers(List.of(new KubernetesObserver(landscapeDescription, applicationEventPublisher, new DefaultKubernetesClient()))); + pool.updateObservers(List.of(new KubernetesObserver(landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()), applicationEventPublisher, new DefaultKubernetesClient()))); } } diff --git a/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java b/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java index 14432af61..d3dfdd520 100644 --- a/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java +++ b/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java @@ -48,13 +48,6 @@ public void onProcessingFinishedEvent(ProcessingFinishedEvent event) { LandscapeDescription landscapeDescription = event.getInput(); Landscape landscape = Objects.requireNonNull(event.getLandscape()); - if (landscapeDescription == null) { - String msg = String.format("No landscape description (input) available. Landscape %s could not be registered for observation", landscape.getIdentifier()); - landscape.getLog().warn(msg); - LOGGER.warn(msg); - return; - } - LandscapeObserverPool pool = observerMap.computeIfAbsent(landscape.getIdentifier(), s -> { LOGGER.info("Registered landscape {} for observation.", landscapeDescription); return new LandscapeObserverPool(taskScheduler, 30 * 1000); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java index 680f36989..8daa75768 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java @@ -2,6 +2,7 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.LandscapeRepository; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.*; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; @@ -31,7 +32,7 @@ class InputFormatHandlerKubernetesTest { void setUp() { SourceReference sourceReference = new SourceReference(null, "k8s"); sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); - inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient)); + inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient), new LandscapeRepository()); } @Test From 0606c902f242fde136ae1a169a058b0866e61055 Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Fri, 6 Aug 2021 11:27:25 +0200 Subject: [PATCH 149/310] change how observer factory creates observers (file/url based on as fallback) --- .../nivio/input/InputFormatHandler.java | 12 ++++++++++-- .../compose2/InputFormatHandlerCompose2.java | 11 ++--------- .../nivio/input/csv/InputFormatHandlerCSV.java | 8 -------- .../nivio/input/dot/InputFormatHandlerDot.java | 9 --------- .../InputFormatHandlerKubernetes.java | 9 +++++---- .../input/kubernetes/KubernetesObserver.java | 10 ++++++++-- .../status/KubernetesObserverRegistry.java | 3 ++- .../input/nivio/InputFormatHandlerNivio.java | 15 ++------------- .../rancher1/InputFormatHandlerRancher1.java | 18 +++++++++++------- .../InputFormatHandlerRancher1API.java | 10 ---------- .../nivio/observation/BaseObserver.java | 2 +- .../observation/LandscapeObserverFactory.java | 16 +++++++++------- .../InputFormatHandlerKubernetesTest.java | 6 ++++-- .../LandscapeObserverFactoryTest.java | 8 ++++---- 14 files changed, 58 insertions(+), 79 deletions(-) diff --git a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java index 8f1236f69..8873df0b8 100644 --- a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java +++ b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java @@ -2,7 +2,9 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.observation.InputFormatObserver; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -33,11 +35,17 @@ public interface InputFormatHandler { /** * Returns an observer for the source reference. * - * @param inner an observer for files or urls + * @param eventPublisher the event publisher to notify + * @param landscape the current landscape * @param sourceReference the {@link SourceReference} to observe * @return observer that can handle the format or null if no observer is available */ @Nullable - InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference); + default InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final Landscape landscape, + @NonNull final SourceReference sourceReference + ) { + return null; + } } diff --git a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java index c4624d70d..76f64602f 100644 --- a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java +++ b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java @@ -10,7 +10,6 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.http.HttpService; -import de.bonndan.nivio.observation.InputFormatObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; @@ -25,7 +24,7 @@ @Service public class InputFormatHandlerCompose2 implements InputFormatHandler { - private static final Logger logger = LoggerFactory.getLogger(InputFormatHandler.class); + private static final Logger logger = LoggerFactory.getLogger(InputFormatHandlerCompose2.class); private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); static { @@ -61,7 +60,7 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape logger.error("Failed to read yml", e); } if (source == null) { - logger.warn("Got null out of yml string " + yml); + logger.warn("Got null out of yml string {}", yml); return; } @@ -72,10 +71,4 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape landscapeDescription.mergeItems(itemDescriptions); } - - @Override - public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { - return inner; - } - } diff --git a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java index cba6c4690..83c349cb0 100644 --- a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java +++ b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java @@ -13,9 +13,7 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.model.Relation; -import de.bonndan.nivio.observation.InputFormatObserver; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.StringReader; @@ -100,12 +98,6 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape landscapeDescription.mergeItems(itemDescriptions); } - @Override - @Nullable - public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { - return inner; - } - private CSVReader getReader(SourceReference reference, String content) { String separator = (String) Optional.ofNullable(reference.getProperty("separator")).orElse(";"); int skipLines = (int) Optional.ofNullable(reference.getProperty("skipLines")).orElse(0); diff --git a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java index f0bab919e..9bdbf5198 100644 --- a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java +++ b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java @@ -6,14 +6,12 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.model.RelationType; -import de.bonndan.nivio.observation.InputFormatObserver; import guru.nidi.graphviz.model.MutableGraph; import guru.nidi.graphviz.parse.Parser; import guru.nidi.graphviz.parse.ParserException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.IOException; @@ -97,11 +95,4 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape } landscapeDescription.mergeItems(itemDescriptions); } - - @Override - @Nullable - public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference) { - return inner; - } - } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index dd3746780..965885d34 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -7,6 +7,7 @@ import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeRepository; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.OwnerReference; @@ -17,6 +18,7 @@ import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.support.StaticApplicationContext; import org.springframework.lang.NonNull; @@ -38,11 +40,10 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { public static final String LABEL_PREFIX = "k8s."; - private LandscapeRepository landscapeRepository; private KubernetesClient client; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - public InputFormatHandlerKubernetes(Optional client, LandscapeRepository landscapeRepository) { + public InputFormatHandlerKubernetes(Optional client) { this.client = client.orElse(null); } @@ -171,8 +172,8 @@ private void crossReferenceService(List service, List owners) } @Override - public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference) { - return new KubernetesObserver(landscapeRepository.findDistinctByIdentifier(sourceReference.getLandscapeDescription().getIdentifier()), new StaticApplicationContext(), this.client); + public InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, @NonNull final Landscape landscape, @NonNull final SourceReference sourceReference) { + return new KubernetesObserver(landscape, eventPublisher, new StaticApplicationContext(), this.client); } private KubernetesClient getClient(String context) { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java index 6cf593d2f..08fe9cc90 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/KubernetesObserver.java @@ -10,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.lang.NonNull; import java.util.List; @@ -23,11 +24,16 @@ public class KubernetesObserver implements InputFormatObserver { private final Landscape landscape; private final ApplicationEventPublisher eventPublisher; + private final StaticApplicationContext applicationContext; private final KubernetesClient kubernetesClient; private List eventList = null; - public KubernetesObserver(@NonNull final Optional landscape, @NonNull final ApplicationEventPublisher eventPublisher, @NonNull final KubernetesClient kubernetesClient) { - this.landscape = landscape.get(); + public KubernetesObserver(@NonNull final Landscape landscape, + @NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final StaticApplicationContext applicationContext, + @NonNull final KubernetesClient kubernetesClient) { + this.landscape = landscape; + this.applicationContext = applicationContext; this.kubernetesClient = kubernetesClient; this.eventPublisher = eventPublisher; } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java index 7eb15f03b..336a9caca 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/KubernetesObserverRegistry.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Service; @@ -45,6 +46,6 @@ public void onProcessingFinishedEvent(ProcessingFinishedEvent event) { LOGGER.info("Registered landscape {} for observation.", landscapeDescription); return new LandscapeObserverPool(taskScheduler, 30 * 1000); }); - pool.updateObservers(List.of(new KubernetesObserver(landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()), applicationEventPublisher, new DefaultKubernetesClient()))); + pool.updateObservers(List.of(new KubernetesObserver(landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()).orElseThrow(), applicationEventPublisher, new StaticApplicationContext(), new DefaultKubernetesClient()))); } } diff --git a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java index c629403a3..de6220445 100644 --- a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java +++ b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java @@ -3,21 +3,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.InputFormatHandler; +import de.bonndan.nivio.input.Mappers; import de.bonndan.nivio.input.ReadingException; -import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.observation.InputFormatObserver; -import de.bonndan.nivio.input.Mappers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -44,7 +40,6 @@ public List getFormats() { @Override public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription description) { - List descriptions = new ArrayList<>(); String yml = fileFetcher.get(reference, baseUrl); Source source; try { @@ -55,7 +50,7 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape } if (source == null) { - logger.warn("Got null out of yml string " + yml); + logger.warn("Got null out of yml string {}", yml); return; } @@ -67,10 +62,4 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape } } - - @Override - @Nullable - public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { - return inner; - } } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java index 6187c9ddc..67afd2970 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1.java @@ -1,20 +1,20 @@ package de.bonndan.nivio.input.rancher1; import de.bonndan.nivio.input.InputFormatHandler; -import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.observation.InputFormatObserver; import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; @Service @@ -24,7 +24,7 @@ public class InputFormatHandlerRancher1 implements InputFormatHandler { @Override public List getFormats() { - return Arrays.asList("rancher1-prometheus"); + return Collections.singletonList("rancher1-prometheus"); } @Override @@ -43,8 +43,12 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape } @Override - public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference sourceReference) { - //TODO add observer - return null; + public InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final Landscape landscape, + @NonNull final SourceReference sourceReference) { + //TODO add observer, or maybe not, since it is deprecated + return () -> { + + }; } } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java index d9431e3dd..0270af63b 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java @@ -1,12 +1,9 @@ package de.bonndan.nivio.input.rancher1; import de.bonndan.nivio.input.InputFormatHandler; -import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.ProcessingException; -import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.observation.InputFormatObserver; import io.rancher.Rancher; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; @@ -34,13 +31,6 @@ public void applyData(@NonNull SourceReference reference, URL baseUrl, Landscape landscapeDescription.mergeItems(apiWalker.getDescriptions()); } - @Override - public InputFormatObserver getObserver(@NonNull InputFormatObserver inner, @NonNull SourceReference reference) { - Rancher.Config config = getConfig(reference); - //TODO add observer - return null; - } - private Rancher.Config getConfig(SourceReference reference) { Rancher.Config config; String accessKey = (String) reference.getProperty(API_ACCESS_KEY); diff --git a/src/main/java/de/bonndan/nivio/observation/BaseObserver.java b/src/main/java/de/bonndan/nivio/observation/BaseObserver.java index 07ee69dfd..8bbc8c2c6 100644 --- a/src/main/java/de/bonndan/nivio/observation/BaseObserver.java +++ b/src/main/java/de/bonndan/nivio/observation/BaseObserver.java @@ -14,7 +14,7 @@ public abstract class BaseObserver implements InputFormatObserver { protected final Landscape landscape; protected final ApplicationEventPublisher eventPublisher; - public BaseObserver(@NonNull final Landscape landscape, @NonNull final ApplicationEventPublisher eventPublisher) { + protected BaseObserver(@NonNull final Landscape landscape, @NonNull final ApplicationEventPublisher eventPublisher) { this.landscape = Objects.requireNonNull(landscape); this.eventPublisher = Objects.requireNonNull(eventPublisher); } diff --git a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java index ac6c43da9..ecc044da1 100644 --- a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java +++ b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java @@ -65,30 +65,32 @@ public List getObserversFor(@NonNull final Landscape landsc if (baseUrl.isEmpty()) { LOGGER.info("Cannot create observer for landscape '{}' source '{}' ", description.getIdentifier(), url.get()); } else { - observers.add(getObserver(landscape, url.get())); + observers.add(getDefaultObserver(landscape, url.get())); } } for (SourceReference sourceReference : description.getSourceReferences()) { InputFormatHandler inputFormatHandler = inputFormatHandlerFactory.getInputFormatHandler(sourceReference); - InputFormatObserver observer; + URL combined; try { - observer = getObserver(landscape, new URL(URLHelper.combine(baseUrl.orElse(null), sourceReference.getUrl()))); + combined = new URL(URLHelper.combine(baseUrl.orElse(null), sourceReference.getUrl())); } catch (MalformedURLException e) { LOGGER.warn("Failed to create observer for base url {} and source reference {}", baseUrl.orElse(null), sourceReference.getUrl()); continue; } + InputFormatObserver observer = inputFormatHandler.getObserver(eventPublisher, landscape, sourceReference); - observer = inputFormatHandler.getObserver(observer, sourceReference); - if (observer != null) { - observers.add(observer); + if (observer == null) { + observer = getDefaultObserver(landscape, combined); } + + observers.add(observer); } return observers; } - private InputFormatObserver getObserver(Landscape landscape, URL url) { + private InputFormatObserver getDefaultObserver(Landscape landscape, URL url) { if (URLHelper.isLocal(url)) { try { return new LocalFileObserver(landscape, eventPublisher, new File(url.toURI())); diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java index 8daa75768..fbea9d572 100644 --- a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java @@ -2,6 +2,7 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeRepository; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.*; @@ -13,6 +14,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.context.ApplicationEventPublisher; import java.net.MalformedURLException; import java.net.URL; @@ -32,7 +34,7 @@ class InputFormatHandlerKubernetesTest { void setUp() { SourceReference sourceReference = new SourceReference(null, "k8s"); sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); - inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient), new LandscapeRepository()); + inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient)); } @Test @@ -111,6 +113,6 @@ private void setK8sTestEnvironment() { @Test void getObserver() { - assertNull(inputFormatHandlerKubernetes.getObserver(Mockito.mock(InputFormatObserver.class), Mockito.mock(SourceReference.class))); + assertNull(inputFormatHandlerKubernetes.getObserver(Mockito.mock(ApplicationEventPublisher.class), Mockito.mock(Landscape.class), Mockito.mock(SourceReference.class))); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java index 64208c9bb..fb2da6b49 100644 --- a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java @@ -59,7 +59,7 @@ public void getObservers() throws MalformedURLException { InputFormatHandler handler = mock(InputFormatHandler.class); InputFormatObserver mockObserver = mock(InputFormatObserver.class); - when(handler.getObserver(any(InputFormatObserver.class), any(SourceReference.class))).thenReturn(mockObserver); + when(handler.getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), any(SourceReference.class))).thenReturn(mockObserver); when(formatFactory.getInputFormatHandler(any(SourceReference.class))).thenReturn(handler); when(fileFetcher.get(any(URL.class))).thenReturn(""); @@ -75,7 +75,7 @@ public void getObservers() throws MalformedURLException { verify(formatFactory).getInputFormatHandler(eq(ref1)); - verify(handler).getObserver(any(InputFormatObserver.class), eq(ref1)); + verify(handler).getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), eq(ref1)); } @Test @@ -91,7 +91,7 @@ public void withoutSourceUrl() { description.getSourceReferences().add(ref1); InputFormatHandler handler = mock(InputFormatHandler.class); - when(handler.getObserver(any(InputFormatObserver.class), any(SourceReference.class))).thenReturn(mock(InputFormatObserver.class)); + when(handler.getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), any(SourceReference.class))).thenReturn(mock(InputFormatObserver.class)); when(formatFactory.getInputFormatHandler(any(SourceReference.class))).thenReturn(handler); //when @@ -104,7 +104,7 @@ public void withoutSourceUrl() { assertEquals(1, observers.size()); verify(formatFactory).getInputFormatHandler(eq(ref1)); - verify(handler).getObserver(any(InputFormatObserver.class), eq(ref1)); + verify(handler).getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), eq(ref1)); } private String getRootPath() { From 6ae7a74a878a3ea528cc5b5b7dfa813b90bf7b4e Mon Sep 17 00:00:00 2001 From: Daniel Pozzi Date: Sat, 7 Aug 2021 06:36:39 +0200 Subject: [PATCH 150/310] [#637] removed deprecated react values --- src/main/app/src/App.tsx | 4 ++-- .../src/Components/Landscape/Dashboard/LandscapeWatcher.tsx | 2 +- .../app/src/Components/Landscape/Modals/Group/GroupAvatar.tsx | 2 +- .../app/src/Components/Landscape/Modals/Item/ItemAvatar.tsx | 2 +- src/main/app/src/Components/Notification/Notification.tsx | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/app/src/App.tsx b/src/main/app/src/App.tsx index 07f85bb2a..a06afc4f7 100644 --- a/src/main/app/src/App.tsx +++ b/src/main/app/src/App.tsx @@ -7,7 +7,7 @@ import Man from './Components/Manual/Man'; import Layout from './Components/Layout/Layout'; import { Routes } from './interfaces'; import { Box, CssBaseline, Theme } from '@material-ui/core'; -import { createMuiTheme, ThemeOptions, ThemeProvider } from '@material-ui/core/styles'; +import { createTheme, ThemeOptions, ThemeProvider } from '@material-ui/core/styles'; import { get } from './utils/API/APIClient'; import defaultThemeVariables from './Resources/styling/theme'; @@ -77,7 +77,7 @@ const App: React.FC = () => { if (index.config.brandingLogoUrl && index.config.brandingLogoUrl.length) { setLogo(index.config.brandingLogoUrl); } - setTheme(createMuiTheme(tv)); + setTheme(createTheme(tv)); }); }, [setTheme, setLogo]); diff --git a/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx b/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx index 2cb2d1893..15aa1b444 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx @@ -51,7 +51,7 @@ const LandscapeWatcher: React.FC = ({ setSidebarContent, ...props }) => { return ( = ({ group, statusColor }) => { return ( = ({ item, statusColor }) => { return ( = ({ setSidebarContent }) => { }, [landscapeContext.notification]); return ( - + Date: Sun, 8 Aug 2021 11:01:54 +0200 Subject: [PATCH 151/310] [#637] introduced AssessmentChangedEvent [#543] introduced ApiModels, internal labels --- docs/source/inc_labels.rst | 3 +- docs/source/schema/Models/Branding.rst | 5 - docs/source/schema/spec.json | 5 - .../app/src/Components/Landscape/Map/Map.tsx | 13 +- src/main/app/src/Context/LandscapeContext.tsx | 10 +- src/main/app/src/interfaces.ts | 1 - src/main/app/src/labels.json | 2 +- .../de/bonndan/nivio/api/ApiController.java | 48 +++++--- .../de/bonndan/nivio/api/LinkFactory.java | 45 +++---- .../bonndan/nivio/assessment/Assessment.java | 11 +- .../assessment/AssessmentChangedEvent.java | 42 +++++++ .../assessment/AssessmentController.java | 2 +- .../assessment/AssessmentRepository.java | 36 +++--- .../assessment/ProcessingEventListener.java | 33 ++++++ .../nivio/assessment/kpi/ConditionKPI.java | 3 +- .../nivio/assessment/kpi/CustomKPI.java | 1 + .../de/bonndan/nivio/assessment/kpi/KPI.java | 1 + .../nivio/assessment/kpi/KubernetesKPI.java | 11 +- .../nivio/assessment/kpi/ScalingKPI.java | 1 + .../nivio/input/AppearanceProcessor.java | 70 ----------- .../java/de/bonndan/nivio/input/Indexer.java | 9 +- .../nivio/input/dto/ItemDescription.java | 9 +- .../InputFormatHandlerKubernetes.java | 3 +- .../input/kubernetes/status/BoolStatus.java | 2 +- .../kubernetes/status/ReplicaStatus.java | 4 +- .../java/de/bonndan/nivio/model/Group.java | 19 +-- .../de/bonndan/nivio/model/GroupBuilder.java | 2 +- .../java/de/bonndan/nivio/model/Item.java | 53 ++------- .../de/bonndan/nivio/model/ItemBuilder.java | 8 +- .../de/bonndan/nivio/model/ItemFactory.java | 7 +- .../java/de/bonndan/nivio/model/Label.java | 18 ++- .../java/de/bonndan/nivio/model/Labeled.java | 13 +- .../de/bonndan/nivio/model/Landscape.java | 2 +- .../bonndan/nivio/model/LandscapeConfig.java | 12 -- .../java/de/bonndan/nivio/model/Relation.java | 53 +-------- .../java/de/bonndan/nivio/model/Tagged.java | 4 +- .../nivio/notification/MessagingService.java | 6 +- .../de/bonndan/nivio/output/Renderer.java | 5 + .../nivio/output/docs/DocsController.java | 3 +- .../nivio/output/docs/HtmlGenerator.java | 35 ++---- .../nivio/output/docs/ReportGenerator.java | 4 +- .../nivio/output/dto/ComponentApiModel.java | 35 ++++++ .../nivio/output/dto/GroupApiModel.java | 61 ++++++++++ .../nivio/output/dto/ItemApiModel.java | 112 ++++++++++++++++++ .../nivio/output/dto/LandscapeApiModel.java | 85 +++++++++++++ .../kpi => output/dto}/RangeApiModel.java | 2 +- .../nivio/output/dto/RelationApiModel.java | 56 +++++++++ .../nivio/output/icons/IconService.java | 5 +- .../output/layout/AppearanceProcessor.java | 43 +++++++ .../nivio/output/layout/LayoutConfig.java | 18 +++ .../nivio/output/layout/LayoutService.java | 70 +++++++++++ .../output/layout/LayoutedComponent.java | 10 +- .../bonndan/nivio/output/layout/Layouter.java | 3 +- .../nivio/output/layout/OrganicLayouter.java | 5 +- .../nivio/output/layout/SubLayout.java | 12 +- .../nivio/output/map/MapController.java | 10 +- .../bonndan/nivio/output/map/RenderCache.java | 81 ------------- .../nivio/output/map/RenderingRepository.java | 51 ++++++++ .../nivio/output/map/svg/SVGDocument.java | 12 +- .../bonndan/nivio/output/map/svg/SVGItem.java | 8 +- .../nivio/output/map/svg/SVGItemLabel.java | 2 +- .../nivio/output/map/svg/SVGRenderer.java | 5 + .../search/SearchIndexingEventListener.java | 18 +-- src/main/resources/application.yml | 3 + .../nivio/assessment/AssessableTest.java | 2 +- .../assessment/AssessmentRepositoryTest.java | 20 ++-- .../ProcessingEventListenerTest.java | 46 +++++++ .../assessment/kpi/ConditionKPITest.java | 6 +- .../bonndan/nivio/assessment/kpi/KPITest.java | 1 + .../assessment/kpi/KubernetesKpiTest.java | 54 ++++++--- .../nivio/input/IndexerIntegrationTest.java | 4 +- .../LandscapeDescriptionFactoryTest.java | 42 +++---- .../input/kubernetes/CreateItemsTest.java | 8 +- .../kubernetes/status/BoolStatusTest.java | 5 +- .../kubernetes/status/ReplicaStatusTest.java | 5 +- .../bonndan/nivio/model/ItemFactoryTest.java | 8 +- .../java/de/bonndan/nivio/model/ItemTest.java | 46 ++----- .../de/bonndan/nivio/model/LabeledTest.java | 22 ++-- .../de/bonndan/nivio/model/RelationTest.java | 13 +- .../bonndan/nivio/output/RenderingTest.java | 42 ++++--- .../nivio/output/dto/ApiModelTest.java | 57 +++++++++ .../nivio/output/dto/ItemApiModelTest.java | 65 ++++++++++ .../nivio/output/icons/IconServiceTest.java | 32 +++-- .../nivio/output/icons/LocalIconsTest.java | 14 +-- .../layout}/AppearanceProcessorTest.java | 47 +------- .../output/layout/LayoutServiceTest.java | 56 +++++++++ .../output/layout/OrganicLayouterTest.java | 27 ++--- .../nivio/output/map/RenderCacheTest.java | 108 ----------------- .../output/map/RenderingRepositoryTest.java | 42 +++++++ .../nivio/output/map/svg/SVGDocumentTest.java | 17 +-- .../nivio/output/map/svg/SVGItemTest.java | 41 +++---- .../search/SearchDocumentFactoryTest.java | 14 +-- .../SearchIndexingEventListenerTest.java | 43 ++----- src/test/resources/example/dedica.yml | 2 +- src/test/resources/example/inout.yml | 2 +- 95 files changed, 1335 insertions(+), 877 deletions(-) create mode 100644 src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java create mode 100644 src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java delete mode 100644 src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java create mode 100644 src/main/java/de/bonndan/nivio/output/dto/ComponentApiModel.java create mode 100644 src/main/java/de/bonndan/nivio/output/dto/GroupApiModel.java create mode 100644 src/main/java/de/bonndan/nivio/output/dto/ItemApiModel.java create mode 100644 src/main/java/de/bonndan/nivio/output/dto/LandscapeApiModel.java rename src/main/java/de/bonndan/nivio/{assessment/kpi => output/dto}/RangeApiModel.java (96%) create mode 100644 src/main/java/de/bonndan/nivio/output/dto/RelationApiModel.java create mode 100644 src/main/java/de/bonndan/nivio/output/layout/AppearanceProcessor.java create mode 100644 src/main/java/de/bonndan/nivio/output/layout/LayoutConfig.java create mode 100644 src/main/java/de/bonndan/nivio/output/layout/LayoutService.java delete mode 100644 src/main/java/de/bonndan/nivio/output/map/RenderCache.java create mode 100644 src/main/java/de/bonndan/nivio/output/map/RenderingRepository.java create mode 100644 src/test/java/de/bonndan/nivio/assessment/ProcessingEventListenerTest.java create mode 100644 src/test/java/de/bonndan/nivio/output/dto/ApiModelTest.java create mode 100644 src/test/java/de/bonndan/nivio/output/dto/ItemApiModelTest.java rename src/test/java/de/bonndan/nivio/{input => output/layout}/AppearanceProcessorTest.java (52%) create mode 100644 src/test/java/de/bonndan/nivio/output/layout/LayoutServiceTest.java delete mode 100644 src/test/java/de/bonndan/nivio/output/map/RenderCacheTest.java create mode 100644 src/test/java/de/bonndan/nivio/output/map/RenderingRepositoryTest.java diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index 1513928c8..a77098c5e 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -1,5 +1,5 @@ * ``capability`` The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence. -* ``color`` A hex color code to override the inherited group color +* ``color`` A hex color code (items inherit group colors as default) * ``costs`` Running costs of the item. * ``fill`` Background image (for displaying purposes). * ``frameworks`` A comma-separated list of frameworks as key-value pairs (key is name, value is version). @@ -14,7 +14,6 @@ * ``software`` Software/OS name. * ``stability`` Description of the item's stability. * ``team`` Name of the responsible team (e.g. technical owner). -* ``type`` The type (service, database, queue, load balancer, etc.). * ``version`` The version (e.g. software version or protocol version). * ``visibility`` Visibility to other items. * ``weight`` Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given. \ No newline at end of file diff --git a/docs/source/schema/Models/Branding.rst b/docs/source/schema/Models/Branding.rst index 71e412368..4c5d95fe5 100644 --- a/docs/source/schema/Models/Branding.rst +++ b/docs/source/schema/Models/Branding.rst @@ -13,11 +13,6 @@ Map branding (tweaks visuals) - Remarks - Example - * - mapLogo - - String - - A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map. - - optional, defaults to null - - https://acme.com/images/logo.png * - mapStylesheet - String - A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map. diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 5228cc83e..aae56fb05 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -11,11 +11,6 @@ "Branding" : { "type" : "object", "properties" : { - "mapLogo" : { - "type" : "string", - "description" : "A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map.", - "example" : "https://acme.com/images/logo.png" - }, "mapStylesheet" : { "type" : "string", "description" : "A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map.", diff --git a/src/main/app/src/Components/Landscape/Map/Map.tsx b/src/main/app/src/Components/Landscape/Map/Map.tsx index b07f09c3e..2899e83c1 100644 --- a/src/main/app/src/Components/Landscape/Map/Map.tsx +++ b/src/main/app/src/Components/Landscape/Map/Map.tsx @@ -194,7 +194,7 @@ const Map: React.FC = ({ setSidebarContent, setPageTitle }) => { }; const loadMap = useCallback(() => { - console.debug('loading map'); + const route = withBasePath(`/render/${identifier}/map.svg`); get(route).then((svg) => { const parser = new DOMParser(); @@ -207,6 +207,7 @@ const Map: React.FC = ({ setSidebarContent, setPageTitle }) => { }, [identifier, setData]); useEffect(() => { + console.log('loading map', new Date()); loadMap(); setSidebarContent(null); }, [identifier, loadMap, setSidebarContent]); @@ -247,13 +248,9 @@ const Map: React.FC = ({ setSidebarContent, setPageTitle }) => { * Reload map on notification messages. */ useEffect(() => { - if ( - landscapeContext.notification?.type === 'ProcessingFinishedEvent' && - landscapeContext.notification?.landscape === landscapeContext.identifier - ) { - loadMap(); - } - }, [landscapeContext.notification, landscapeContext.identifier, loadMap]); + console.debug("reloading map", landscapeContext.assessment); + loadMap(); + }, [landscapeContext.assessment, landscapeContext.identifier, loadMap]); useEffect(() => { let timeout: NodeJS.Timeout; diff --git a/src/main/app/src/Context/LandscapeContext.tsx b/src/main/app/src/Context/LandscapeContext.tsx index ee8b6360e..6d6fd0be0 100644 --- a/src/main/app/src/Context/LandscapeContext.tsx +++ b/src/main/app/src/Context/LandscapeContext.tsx @@ -55,9 +55,7 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { const subscriptions: StompSubscription[] = []; const eventSubscription = client.subscribe('/topic/events', (message) => { const notificationMessage: INotificationMessage = JSON.parse(message.body); - if (notificationMessage.type === 'ProcessingFinishedEvent') { - setNotification(notificationMessage); - } + setNotification(notificationMessage); }); subscriptions.push(eventSubscription); @@ -89,11 +87,11 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { get(`/api/${identifier}`).then((response) => { setLandscape(response); - console.debug(`Loaded landscape data for ${identifier}`); + console.debug(`Loaded landscape data after identifier change: ${identifier}`); }); get(`/assessment/${identifier}`).then((response) => { setAssessment(response); - console.debug(`Loaded assessment data for ${identifier}`); + console.debug(`Loaded assessment data after identifier change: ${identifier}`); }); }, [identifier]); @@ -107,8 +105,8 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { } get(`/assessment/${identifier}`).then((response) => { + console.log(`Loaded assessment data for ${identifier}`, response); setAssessment(response); - console.debug(`Loaded assessment data for ${identifier}`); }); }, [identifier, notification]); diff --git a/src/main/app/src/interfaces.ts b/src/main/app/src/interfaces.ts index 88d9ceb15..f8604bcff 100644 --- a/src/main/app/src/interfaces.ts +++ b/src/main/app/src/interfaces.ts @@ -109,7 +109,6 @@ export interface IItem { tags: Array; color?: string; icon: string; - links?: Object; _links?: ILinks; } diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index 9c419ae66..5a77c4d44 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -1 +1 @@ -{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items.","weight":"Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."} \ No newline at end of file +{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code (items inherit group colors as default)","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items.","weight":"Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/api/ApiController.java b/src/main/java/de/bonndan/nivio/api/ApiController.java index bbd9bffd5..be210b2ff 100644 --- a/src/main/java/de/bonndan/nivio/api/ApiController.java +++ b/src/main/java/de/bonndan/nivio/api/ApiController.java @@ -4,6 +4,9 @@ import de.bonndan.nivio.input.ProcessLog; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.model.*; +import de.bonndan.nivio.output.dto.GroupApiModel; +import de.bonndan.nivio.output.dto.ItemApiModel; +import de.bonndan.nivio.output.dto.LandscapeApiModel; import org.apache.lucene.facet.FacetResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,8 +19,10 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; @RestController @RequestMapping(path = ApiController.PATH) @@ -57,15 +62,15 @@ public Index index() { */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity landscape(@PathVariable String landscapeIdentifier) { + public ResponseEntity landscape(@PathVariable String landscapeIdentifier) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeIdentifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } - //TODO this modifies the landscape components by adding SELF links - linkFactory.setLandscapeLinksRecursive(landscape); - return new ResponseEntity<>(landscape, HttpStatus.OK); + LandscapeApiModel landscapeApiModel = new LandscapeApiModel(landscape); + linkFactory.setLandscapeLinksRecursive(landscapeApiModel); + return new ResponseEntity<>(landscapeApiModel, HttpStatus.OK); } /** @@ -73,19 +78,19 @@ public ResponseEntity landscape(@PathVariable String landscapeIdentif */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}/{groupIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity group(@PathVariable String landscapeIdentifier, - @PathVariable String groupIdentifier + public ResponseEntity group(@PathVariable String landscapeIdentifier, + @PathVariable String groupIdentifier ) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeIdentifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } - //TODO this modifies the landscape components by adding SELF links Optional group = landscape.getGroup(groupIdentifier); if (group.isPresent()) { - linkFactory.setGroupLinksRecursive(group.get()); - return new ResponseEntity<>(group.get(), HttpStatus.OK); + GroupApiModel groupItem = new GroupApiModel(group.get()); + linkFactory.setGroupLinksRecursive(groupItem); + return new ResponseEntity<>(groupItem, HttpStatus.OK); } else { return ResponseEntity.notFound().build(); } @@ -96,7 +101,7 @@ public ResponseEntity group(@PathVariable String landscapeIdentifier, */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}/{groupIdentifier}/{itemIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity item(@PathVariable String landscapeIdentifier, + public ResponseEntity item(@PathVariable String landscapeIdentifier, @PathVariable String groupIdentifier, @PathVariable String itemIdentifier ) { @@ -109,16 +114,17 @@ public ResponseEntity item(@PathVariable String landscapeIdentifier, if (item.isEmpty()) { return ResponseEntity.notFound().build(); } - Item item1 = item.get(); - linkFactory.setItemSelfLink(item1); - return new ResponseEntity<>(item1, HttpStatus.OK); + Group group = landscape.getGroup(groupIdentifier).orElseThrow(); + ItemApiModel apiModel = new ItemApiModel(item.get(), group); + linkFactory.setItemSelfLink(apiModel); + return new ResponseEntity<>(apiModel, HttpStatus.OK); } /** * Creates a new landscape */ @PostMapping(path = "/landscape") - public ResponseEntity create(@RequestBody String body) throws URISyntaxException { + public ResponseEntity create(@RequestBody String body) { LandscapeDescription env = indexingDispatcher.createFromBody(body); Optional uriForDTO = getURIForDTO(env); return uriForDTO @@ -131,7 +137,7 @@ public ResponseEntity addItems( @PathVariable String identifier, @RequestHeader(name = "format") String format, @RequestBody String body - ) throws URISyntaxException { + ) { LandscapeDescription dto = indexingDispatcher.createFromBodyItems(identifier, format, body); Optional uriForDTO = getURIForDTO(dto); return uriForDTO @@ -153,15 +159,19 @@ public ResponseEntity log(@PathVariable String identifier) { @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/landscape/{identifier}/search/{query}", produces = "application/json") - public ResponseEntity> search(@PathVariable String identifier, @PathVariable String query) { + public ResponseEntity> search(@PathVariable String identifier, @PathVariable String query) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(identifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } + Map groups = landscape.getGroups(); try { - return new ResponseEntity<>(landscape.search(query), HttpStatus.OK); + Set results = landscape.search(query).stream() + .map(item -> new ItemApiModel(item, groups.get(item.getGroup()))) + .collect(Collectors.toSet()); + return new ResponseEntity<>(results, HttpStatus.OK); } catch (RuntimeException error) { LOGGER.error("Search query '{}' in landscape {} failed: {}", query, landscape, error.getMessage(), error); return ResponseEntity.badRequest().build(); @@ -186,7 +196,7 @@ public ResponseEntity> facets(@PathVariable String identifier) * Trigger reindexing of a landscape source. */ @PostMapping(path = "/reindex/{landscape}") - public ResponseEntity reindex(@PathVariable String landscape) throws URISyntaxException { + public ResponseEntity reindex(@PathVariable String landscape) { Landscape existing = landscapeRepository.findDistinctByIdentifier(landscape).orElse(null); if (existing == null) { return ResponseEntity.notFound().build(); @@ -200,7 +210,7 @@ public ResponseEntity reindex(@PathVariable String landscape) throws URI } private Optional getURIForDTO(LandscapeDescription env) { - Optional link = Optional.ofNullable(linkFactory.generateComponentLink(env.getFullyQualifiedIdentifier())); + Optional link = linkFactory.generateComponentLink(env.getFullyQualifiedIdentifier()); if (link.isEmpty()) { return Optional.empty(); } diff --git a/src/main/java/de/bonndan/nivio/api/LinkFactory.java b/src/main/java/de/bonndan/nivio/api/LinkFactory.java index 6a47d5697..26f6fa293 100644 --- a/src/main/java/de/bonndan/nivio/api/LinkFactory.java +++ b/src/main/java/de/bonndan/nivio/api/LinkFactory.java @@ -5,15 +5,15 @@ import de.bonndan.nivio.model.*; import de.bonndan.nivio.output.LocalServer; import de.bonndan.nivio.output.docs.DocsController; +import de.bonndan.nivio.output.dto.GroupApiModel; +import de.bonndan.nivio.output.dto.ItemApiModel; +import de.bonndan.nivio.output.dto.LandscapeApiModel; import de.bonndan.nivio.output.map.MapController; import org.springframework.http.MediaType; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.StreamSupport; import static de.bonndan.nivio.model.Link.LinkBuilder.linkTo; @@ -35,9 +35,10 @@ public LinkFactory(LocalServer localServer, NivioConfigProperties configProperti this.configProperties = configProperties; } - public Map getLandscapeLinks(Landscape landscape) { + public Map getLandscapeLinks(LandscapeApiModel landscape) { Map links = new HashMap<>(); - links.put(REL_SELF, generateComponentLink(landscape.getFullyQualifiedIdentifier())); + generateComponentLink(landscape.getFullyQualifiedIdentifier()) + .ifPresent(link -> links.put(REL_SELF, link)); localServer.getUrl(ApiController.PATH, "reindex", landscape.getIdentifier()).ifPresent(url -> { links.put("reindex", linkTo(url) @@ -81,7 +82,6 @@ public Map getLandscapeLinks(Landscape landscape) { ); }); - localServer.getUrl(AssessmentController.PATH, landscape.getFullyQualifiedIdentifier().toString()).ifPresent(url -> { links.put("assessment", linkTo(url) .withMedia(MediaType.APPLICATION_JSON_VALUE) @@ -90,7 +90,6 @@ public Map getLandscapeLinks(Landscape landscape) { ); }); - return links; } @@ -100,14 +99,14 @@ public Map getLandscapeLinks(Landscape landscape) { * @param fullyQualifiedIdentifier the component's fqi * @return link based on the {@link FullyQualifiedIdentifier} */ - @Nullable - public Link generateComponentLink(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier) { + @NonNull + public Optional generateComponentLink(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier) { return localServer.getUrl(ApiController.PATH, Objects.requireNonNull(fullyQualifiedIdentifier).jsonValue()) .map(url -> linkTo(url) .withMedia(MediaType.APPLICATION_JSON_VALUE) .withTitle("JSON representation") .build() - ).orElse(null); + ); } /** @@ -139,26 +138,20 @@ Index getIndex(Iterable landscapes) { * * @param landscape landscape */ - void setLandscapeLinksRecursive(Landscape landscape) { + void setLandscapeLinksRecursive(LandscapeApiModel landscape) { Map landscapeLinks = getLandscapeLinks(landscape); - landscape.setLinks(landscapeLinks); - setGroupSelfLinksRecursive(landscape.getGroups()); - } - - void setGroupSelfLinksRecursive(Map groups) { - groups.forEach((s, groupItem) -> setGroupLinksRecursive(groupItem)); + landscape.setHateoasLinks(landscapeLinks); + landscape.getGroups().forEach(this::setGroupLinksRecursive); } - void setGroupLinksRecursive(Group groupItem) { - if (!groupItem.getLinks().containsKey(REL_SELF)) { - groupItem.getLinks().put(REL_SELF, generateComponentLink(groupItem.getFullyQualifiedIdentifier())); - } + void setGroupLinksRecursive(GroupApiModel groupItem) { + generateComponentLink(groupItem.getFullyQualifiedIdentifier()) + .ifPresent(link -> groupItem.setHateoasLinks(Map.of(REL_SELF, link))); groupItem.getItems().forEach(this::setItemSelfLink); } - void setItemSelfLink(Item item) { - if (!item.getLinks().containsKey(REL_SELF)) { - item.getLinks().put(REL_SELF, generateComponentLink(item.getFullyQualifiedIdentifier())); - } + void setItemSelfLink(ItemApiModel item) { + generateComponentLink(item.getFullyQualifiedIdentifier()) + .ifPresent(link -> item.setHateoasLinks(Map.of(REL_SELF, link))); } } diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessment.java b/src/main/java/de/bonndan/nivio/assessment/Assessment.java index e5353cfc6..568828cea 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessment.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessment.java @@ -8,8 +8,6 @@ /** * Result of a landscape (or group, or item) assessment using {@link AbstractKPI}s. - * - * */ public class Assessment { @@ -21,6 +19,15 @@ public Assessment(Map> results) { this.results = results; } + /** + * Null-object + * + * @return an empty instance + */ + public static Assessment empty() { + return new Assessment(Map.of()); + } + public Map> getResults() { return results; } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java new file mode 100644 index 000000000..425abf03f --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.input.ProcessingEvent; +import de.bonndan.nivio.model.Landscape; +import org.springframework.lang.NonNull; + +import java.util.Objects; + +public class AssessmentChangedEvent extends ProcessingEvent { + + private final Landscape landscape; + private final Assessment assessment; + + public AssessmentChangedEvent(@NonNull final Landscape landscape, @NonNull final Assessment assessment) { + super(Objects.requireNonNull(landscape).getFullyQualifiedIdentifier()); + this.landscape = landscape; + this.assessment = Objects.requireNonNull(assessment); + } + + @Override + public String getLevel() { + return ProcessingEvent.LOG_LEVEL_INFO; + } + + @Override + public String getType() { + return getClass().getSimpleName(); + } + + @Override + public String getMessage() { + return null; + } + + public Landscape getLandscape() { + return landscape; + } + + public Assessment getAssessment() { + return assessment; + } +} diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java index b8898cb0f..a2c24f4b7 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java @@ -32,7 +32,7 @@ public ResponseEntity landscape(@PathVariable String identifier) { var optionalAssessment = assessmentRepository.getAssessment(fqi); if (optionalAssessment.isEmpty()) { - return new ResponseEntity<>(assessmentRepository.createAssessment(landscape), HttpStatus.OK); + return new ResponseEntity<>(assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()).orElse(Assessment.empty()), HttpStatus.OK); } else { return new ResponseEntity<>(optionalAssessment.get(), HttpStatus.OK); } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java index d500c1e32..3a7a19433 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java @@ -1,14 +1,14 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Landscape; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; -import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; /** * Stores and loads and creates Assessments with FullyQualifiedIdentifier as key @@ -16,30 +16,34 @@ @Component public class AssessmentRepository { - private final HashMap repository; + private final Map repository; public AssessmentRepository() { - repository = new HashMap<>(); + repository = new ConcurrentHashMap<>(); } public void clean() { repository.clear(); } + /** + * Returns the current assessment for the landscape. + * + * @param fullyQualifiedIdentifier landscape identifier + * @return an assessment if present + */ @NonNull - public Assessment createAssessment(@NonNull Landscape landscape) { - var testedLandscape = Objects.requireNonNull(landscape, "Assessments can't be created from a null value"); - var newAssessment = AssessmentFactory.createAssessment(testedLandscape); - storeAssessment(testedLandscape.getFullyQualifiedIdentifier(), newAssessment); - return newAssessment; + public Optional getAssessment(@NonNull final FullyQualifiedIdentifier fullyQualifiedIdentifier) { + return Optional.ofNullable(repository.get(Objects.requireNonNull(fullyQualifiedIdentifier, "Null instead of FQI given"))); } - public Optional getAssessment(@Nullable FullyQualifiedIdentifier fullyQualifiedIdentifier) { - return Optional.ofNullable(repository.get(fullyQualifiedIdentifier)); + /** + * Saves the given assessment + * + * @param fqi landscape identifier + * @param assessment assessment + */ + public void save(@NonNull final FullyQualifiedIdentifier fqi, @NonNull final Assessment assessment) { + repository.put(fqi, assessment); } - - private void storeAssessment(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier, @NonNull Assessment assessment) { - repository.put(fullyQualifiedIdentifier, assessment); - } - } diff --git a/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java b/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java new file mode 100644 index 000000000..c5622f63d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java @@ -0,0 +1,33 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.input.ProcessingFinishedEvent; +import de.bonndan.nivio.model.Landscape; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * Creates a new assessment after a {@link ProcessingFinishedEvent} + * + * + */ +@Component +public class ProcessingEventListener { + + private final AssessmentRepository repository; + private final ApplicationEventPublisher publisher; + + public ProcessingEventListener(final AssessmentRepository repository, final ApplicationEventPublisher publisher) { + this.repository = repository; + this.publisher = publisher; + } + + @EventListener(ProcessingFinishedEvent.class) + public void onProcessingFinishedEvent(final ProcessingFinishedEvent processingEvent) { + Landscape landscape = processingEvent.getLandscape(); + Assessment assessment = AssessmentFactory.createAssessment(landscape); + repository.save(landscape.getFullyQualifiedIdentifier(), assessment); + publisher.publishEvent(new AssessmentChangedEvent(landscape, assessment)); + } + +} diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java index 32e551482..913f0ccf4 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java @@ -6,6 +6,7 @@ import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; @@ -37,7 +38,7 @@ public List getStatusValues(Assessable component) { var status = Status.UNKNOWN; var message = ""; - for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { + for (Map.Entry entry : ((Labeled) component).getLabels(Label._condition).entrySet()) { String key = entry.getKey(); String flag = entry.getValue(); if (StringUtils.isEmpty(flag)) diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java index 163ae97bf..d7983ff97 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java @@ -5,6 +5,7 @@ import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java index afb41f501..cf1b3f335 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java @@ -6,6 +6,7 @@ import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Component; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java index fc5e8a937..bbfdffe46 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -3,8 +3,9 @@ import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.apache.commons.collections.map.SingletonMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,18 +24,18 @@ public class KubernetesKPI implements KPI { @Override @NonNull public List getStatusValues(Assessable assessable) { - if (!(assessable instanceof Labeled)) + if (!(assessable instanceof Labeled)) { return new ArrayList<>(); - + } var statusList = new ArrayList(); var counter = new AtomicInteger(0); - ((Labeled) assessable).getLabels(Label.k8s).forEach((key, value) -> { + ((Labeled) assessable).getLabels(InputFormatHandlerKubernetes.LABEL_PREFIX).forEach((key, value) -> { if (ObjectUtils.isEmpty(value)) { return; } StatusValue statusValue; - var message = key.replaceFirst("k8s.", ""); + var message = key.replaceFirst(InputFormatHandlerKubernetes.LABEL_PREFIX + ".", ""); if (message.startsWith("boolcondition.")) { message = message.replaceFirst("boolcondition.", ""); statusValue = new StatusValue(IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java index 2144f83dc..35aaefa41 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java @@ -6,6 +6,7 @@ import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.apache.commons.lang3.Range; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java b/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java deleted file mode 100644 index fd6b0d2ec..000000000 --- a/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.bonndan.nivio.input; - -import de.bonndan.nivio.input.dto.LandscapeDescription; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Label; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.output.icons.IconService; -import de.bonndan.nivio.util.URLHelper; -import org.springframework.lang.NonNull; -import org.springframework.util.StringUtils; - -import java.util.List; -import java.util.Optional; - -/** - * Resolves color and icons for {@link de.bonndan.nivio.model.Component} - * - * Appearance must be determined after indexing, because values might be needed in api, too. - */ -public class AppearanceProcessor extends Processor { - - /** - * see https://github.com/dedica-team/nivio/issues/543 - */ - public static final List affectedLabels = List.of(Label.icon.name(), Label.fill.name(), Label.color.name()); - - private final IconService iconService; - - public AppearanceProcessor(ProcessLog processLog, IconService iconService) { - super(processLog); - this.iconService = iconService; - } - - @Override - public ProcessingChangelog process(@NonNull final LandscapeDescription input, @NonNull final Landscape landscape) { - - Optional logo = Optional.ofNullable(landscape.getConfig().getBranding().getMapLogo()); - logo.ifPresent(s -> setLandscapeLogo(landscape, s)); - - landscape.getGroupItems().forEach(group -> group.getItems().forEach(item -> setItemAppearance(group, item))); - - return new ProcessingChangelog(); - } - - private void setItemAppearance(Group group, Item item) { - - item.setLabel(Label.icon, iconService.getIconUrl(item)); - String fill = item.getLabel(Label.fill); - if (!StringUtils.isEmpty(fill)) { - URLHelper.getURL(fill) - .flatMap(iconService::getExternalUrl) - .ifPresent(s -> item.setLabel(Label.fill, s)); - } - - if (StringUtils.isEmpty(item.getColor())) { - item.setLabel(Label.color, group.getColor()); - } - } - - private void setLandscapeLogo(Landscape landscape, String logo) { - if (StringUtils.isEmpty(logo)) { - return; - } - URLHelper.getURL(logo) - .flatMap(iconService::getExternalUrl) - .ifPresent(s -> landscape.setLabel("logo", s)); - } - -} diff --git a/src/main/java/de/bonndan/nivio/input/Indexer.java b/src/main/java/de/bonndan/nivio/input/Indexer.java index ce8d2cba8..03eaec8a2 100644 --- a/src/main/java/de/bonndan/nivio/input/Indexer.java +++ b/src/main/java/de/bonndan/nivio/input/Indexer.java @@ -6,7 +6,6 @@ import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.model.LandscapeRepository; -import de.bonndan.nivio.output.icons.IconService; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; @@ -20,19 +19,16 @@ public class Indexer { private final InputFormatHandlerFactory formatFactory; private final LinkHandlerFactory linkHandlerFactory; private final ApplicationEventPublisher eventPublisher; - private final IconService iconService; public Indexer(LandscapeRepository landscapeRepository, InputFormatHandlerFactory formatFactory, LinkHandlerFactory linkHandlerFactory, - ApplicationEventPublisher eventPublisher, - IconService iconService + ApplicationEventPublisher eventPublisher ) { this.landscapeRepo = landscapeRepository; this.formatFactory = formatFactory; this.linkHandlerFactory = linkHandlerFactory; this.eventPublisher = eventPublisher; - this.iconService = iconService; } /** @@ -111,9 +107,6 @@ private ProcessingChangelog runResolvers(LandscapeDescription input, Landscape l // create relations between items changelog.merge(new ItemRelationProcessor(logger).process(input, landscape)); - // ensures that items have a resolved icon in the api - new AppearanceProcessor(logger, iconService).process(input, landscape); - return changelog; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index d2c2370bf..8984b9fa6 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -70,6 +70,9 @@ public class ItemDescription implements ComponentDescription, Labeled, Linked, T @Schema(description = "The technical address of the item (should be an URI). Taken into account when matching relation endpoints.") private String address; + @Schema(description = "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", example = "service|database|volume") + private String type; + public ItemDescription() { } @@ -105,14 +108,12 @@ public void setEnvironment(String environment) { this.environment = environment; } - @Schema(description = "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - example = "service|database|volume") public String getType() { - return getLabel(Label.type); + return type; } public void setType(String type) { - this.setLabel(Label.type, type); + this.type = type; } public String getName() { diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index b56dd28fd..cdb4128ec 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -7,6 +7,7 @@ import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; +import de.bonndan.nivio.model.Label; import de.bonndan.nivio.observation.InputFormatObserver; import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.client.Config; @@ -34,7 +35,7 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { public static final String NAMESPACE = "namespace"; - public static final String LABEL_PREFIX = "k8s."; + public static final String LABEL_PREFIX = Label.INTERNAL_LABEL_PREFIX + "k8s"; private KubernetesClient client; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java index 23c365d21..0c167c9dc 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -14,7 +14,7 @@ public class BoolStatus implements Status { @Override public Map getExtendedStatus(@NonNull Map statusMap, @Nullable ItemAdapter itemAdapter) { return statusMap.entrySet().stream().collect(Collectors.toMap( - pair -> InputFormatHandlerKubernetes.LABEL_PREFIX + "boolcondition." + pair.getKey().toLowerCase(), + pair -> InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition." + pair.getKey().toLowerCase(), pair -> pair.getValue().toLowerCase(Locale.ROOT) )); } diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java index 9421806f6..a7267f882 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -14,10 +14,10 @@ public class ReplicaStatus implements Status { public Map getExtendedStatus(@NonNull Map statusMap, @NonNull ItemAdapter itemAdapter) { if (itemAdapter instanceof ReplicaSetItemAdapter) { var concreteItem = (ReplicaSetItemAdapter) itemAdapter; - return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + "replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else if (itemAdapter instanceof StatefulSetItemAdapter) { var concreteItem = (StatefulSetItemAdapter) itemAdapter; - return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + "replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); } else { return statusMap; } diff --git a/src/main/java/de/bonndan/nivio/model/Group.java b/src/main/java/de/bonndan/nivio/model/Group.java index 44777d7a7..727b14871 100644 --- a/src/main/java/de/bonndan/nivio/model/Group.java +++ b/src/main/java/de/bonndan/nivio/model/Group.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.model; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.output.Color; @@ -141,28 +140,12 @@ public Set getItems() { return Collections.unmodifiableSet(items); } - @JsonIgnore @Override @NonNull public Map getLabels() { return labels; } - /** - * Returns the labels without the internal ones (having prefixes). - * - * @return filtered labels - */ - @JsonProperty("labels") - public Map getJSONLabels() { - - return Labeled.groupedByPrefixes( - Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG), - "," - ); - } - - @Override @Nullable public String getLabel(String key) { @@ -185,7 +168,7 @@ public String getAssessmentIdentifier() { return getFullyQualifiedIdentifier().toString(); } - @JsonIgnore + @JsonIgnore //for internal debugging @Override @NonNull public List getChildren() { diff --git a/src/main/java/de/bonndan/nivio/model/GroupBuilder.java b/src/main/java/de/bonndan/nivio/model/GroupBuilder.java index 463edbba6..5ada485db 100644 --- a/src/main/java/de/bonndan/nivio/model/GroupBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/GroupBuilder.java @@ -3,7 +3,7 @@ import java.util.HashMap; import java.util.Map; -final class GroupBuilder { +public final class GroupBuilder { private Map links = new HashMap<>(); private String identifier; private String landscapeIdentifier; diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 2e0307b91..481ff7e4b 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -4,9 +4,7 @@ import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.input.ItemRelationProcessor; -import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; import de.bonndan.nivio.output.Color; -import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; @@ -19,8 +17,7 @@ import static de.bonndan.nivio.model.ComponentDiff.*; -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "fullyQualifiedIdentifier") -@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "fullyQualifiedIdentifier") //needed when internal models are serialized for debugging public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent { public static final String LAYER_INFRASTRUCTURE = "infrastructure"; @@ -34,8 +31,7 @@ public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent private final String identifier; @NotNull - @JsonIgnore - @Schema(hidden = true) + @JsonIgnore //needed when internal models are serialized for debugging private final Landscape landscape; private final String name; @@ -48,6 +44,8 @@ public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent private final String group; + private final String type; + /** * technical address */ @@ -74,24 +72,25 @@ public Item(@NotNull final String identifier, final String description, final String color, final String icon, + final String type, final URI address ) { - if (StringUtils.isEmpty(identifier)) { - throw new RuntimeException("Identifier must not be empty"); + if (!StringUtils.hasLength(identifier)) { + throw new IllegalArgumentException("Identifier must not be empty"); } this.identifier = identifier.toLowerCase(); this.landscape = Objects.requireNonNull(landscape, "Landscape must not be null"); - if (StringUtils.isEmpty(group)) { - throw new RuntimeException("Group identifier must not be empty"); + if (!StringUtils.hasLength(group)) { + throw new IllegalArgumentException("Group identifier must not be empty"); } this.group = group; - this.name = name; this.owner = owner; this.contact = contact; this.description = description; this.address = address; + this.type = type; //these are effectively mutable this.setLabel(Label.color, Color.safe(color)); @@ -137,7 +136,6 @@ public String getContact() { return contact; } - @Schema(name = "_links") public Map getLinks() { return links; } @@ -152,29 +150,17 @@ public String getDescription() { } @NonNull - @JsonIgnore @Override public Map getLabels() { return labels; } - /** - * Returns the labels without the internal ones (having prefixes). - * - * @return filtered labels - * @todo find a better way to exclude label "namespaces". Here we introduce unnecessary coupling. - */ - @JsonProperty("labels") - public Map getJSONLabels() { - return Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG, Label.type.name(), Label.icon.name(), InputFormatHandlerKubernetes.LABEL_PREFIX); - } - /** * Returns the relations. * * @return immutable set */ - @JsonIgnore + @JsonIgnore //needed for internal debugging public Set getRelations() { return Set.copyOf(relations); } @@ -214,25 +200,13 @@ private Optional getSimilar(Relation relation) { .findFirst(); } - @JsonProperty("relations") - public Map getJSONRelations() { - Map map = new HashMap<>(); - - relations.forEach(relation -> { - Relation.ApiModel apiModel = new Relation.ApiModel(relation, this); - map.put(apiModel.id, apiModel); - }); - - return map; - } - void setRelations(Set outgoing) { this.relations.clear(); this.relations.addAll(outgoing); } public String getType() { - return getLabel(Label.type); + return type; } public String getAddress() { @@ -248,7 +222,6 @@ public Set getInterfaces() { } @Override - @JsonAnyGetter public String getLabel(String key) { return labels.get(key); } @@ -259,7 +232,6 @@ public Map getLabels(String prefix) { } @Override - @JsonAnySetter public void setLabel(String key, String value) { labels.put(key, value); } @@ -330,6 +302,7 @@ public List getChanges(final Item newer) { changes.addAll(compareStrings(this.description, newer.description, "Description")); changes.addAll(compareStrings(this.name, newer.name, "Name")); changes.addAll(compareStrings(this.owner, newer.owner, "Owner")); + changes.addAll(compareStrings(this.type, newer.type, "Type")); changes.addAll(compareOptionals(Optional.ofNullable(this.address), Optional.ofNullable(newer.address), "Address")); changes.addAll(compareCollections(this.links.keySet(), newer.links.keySet(), "Links")); changes.addAll(newer.diff(this)); diff --git a/src/main/java/de/bonndan/nivio/model/ItemBuilder.java b/src/main/java/de/bonndan/nivio/model/ItemBuilder.java index 68423a700..e387ac0ca 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/ItemBuilder.java @@ -20,6 +20,7 @@ public final class ItemBuilder { private String group; private String color; private String icon; + private String type; private URI address; private Map labels = new HashMap<>(); @@ -90,6 +91,11 @@ public ItemBuilder withIcon(String icon) { return this; } + public ItemBuilder withType(String type) { + this.type = type; + return this; + } + public ItemBuilder withAddress(URI address) { this.address = address; return this; @@ -97,7 +103,7 @@ public ItemBuilder withAddress(URI address) { public Item build() { Item item = new Item(identifier, landscape, group, name, owner, contact, - description, color, icon, address); + description, color, icon, type, address); item.setLinks(links); item.getLabels().putAll(labels); item.setRelations(relations); diff --git a/src/main/java/de/bonndan/nivio/model/ItemFactory.java b/src/main/java/de/bonndan/nivio/model/ItemFactory.java index e5a3df465..0379eef27 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemFactory.java +++ b/src/main/java/de/bonndan/nivio/model/ItemFactory.java @@ -26,7 +26,7 @@ public static Item getTestItem(String group, String identifier) { public static Item getTestItem(String group, String identifier, Landscape landscape) { return new Item(identifier, landscape, group, null,null,null, - null, null, null, null); + null, null, null, null, null); } public static ItemBuilder getTestItemBuilder(String group, String identifier) { @@ -45,6 +45,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca .withOwner(description.getOwner()) .withGroup(description.getGroup()) .withIcon(description.getIcon()) + .withType(description.getType()) .withLandscape(landscape); if (description.getAddress() != null) { @@ -58,7 +59,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca builder.withLinks(description.getLinks()); builder.withLabels(description.getLabels()); - if (StringUtils.isEmpty(builder.getGroup())) { + if (!StringUtils.hasLength(builder.getGroup())) { builder.withGroup(Group.COMMON); } return builder.build(); @@ -85,6 +86,7 @@ public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescr .withOwner(item.getOwner()) .withGroup(item.getGroup()) .withIcon(item.getIcon()) + .withType(item.getType()) .withLandscape(item.getLandscape()) .withRelations(item.getRelations()) .withInterfaces(item.getInterfaces()) @@ -103,6 +105,7 @@ public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescr builder.withOwner(description.getOwner()); builder.withColor(description.getColor()); builder.withIcon(description.getIcon()); + builder.withType(description.getType()); builder.withContact(description.getContact()); builder.withLabels(description.getLabels()); diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 7cfe999bd..1203a47cd 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -15,16 +15,18 @@ public enum Label { capability("The capability the service provides for the business or, in case of infrastructure," + " the technical capability like enabling service discovery, configuration, secrets, or persistence."), - color("A hex color code to override the inherited group color"), + color("A hex color code (items inherit group colors as default)"), costs("Running costs of the item."), fill("Background image (for displaying purposes)."), + _filldata("Background image resolved to a data-url."), framework("A map of used frameworks (key is name, value is version).", true), frameworks("A comma-separated list of frameworks as key-value pairs (key is name, value is version)."), icon("Icon/image (for displaying purposes)."), + _icondata("Icon/image resolved to a data-url"), health("Description of the item's health status."), @@ -46,8 +48,6 @@ public enum Label { team("Name of the responsible team (e.g. technical owner)."), - type("The type (service, database, queue, load balancer, etc.)."), - version("The version (e.g. software version or protocol version)."), visibility("Visibility to other items."), @@ -56,11 +56,11 @@ public enum Label { status("Prefix for status labels. Can be used as prefix for all other labels to mark a status for the label.", true), - condition("Prefix for condition labels.", true), + _condition("Prefix for condition labels.", true), - weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given."), + weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given.") - k8s("Prefix for k8s labels.", true); + ; /** * Separator for label key parts. @@ -68,6 +68,11 @@ public enum Label { */ static final String DELIMITER = "."; + /** + * Internal labels start with an underscore. They are not diffed and not part of the public api. + */ + public static final String INTERNAL_LABEL_PREFIX = "_"; + public final String meaning; public final boolean isPrefix; @@ -117,6 +122,7 @@ public static Map export(boolean includePrefixes) { List