Skip to content

Commit

Permalink
Markers shown on Spring application.yml (#52)
Browse files Browse the repository at this point in the history
* Markers shown on Spring application.yml

* Introduce Traits to match KubernetesResources

* Push kind check down into matcher

* Add missing license header

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Rename variable to prevent confusion

* Filter before map

* Null safe equals

* Use AtomicBoolean for search logic

* Inline return

* Use JsonPathMatcher directly & short circuit after found

* Only create KubernetesModel conditionally

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
timtebeek and github-actions[bot] authored Aug 7, 2024
1 parent 8e3d376 commit b711be6
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
* @deprecated Unused; likely better served by {@link org.openrewrite.kubernetes.trait.Traits}.
*/
@Deprecated
public final class KubernetesParser extends YamlParser {

private static final Pattern METADATA_LABEL = Pattern.compile("/metadata/labels/(.+)");
private static final Pattern METADATA_ANNOTATION = Pattern.compile("/metadata/annotations/(.+)");

public static Builder builder() {
return new Builder();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
import org.openrewrite.yaml.YamlVisitor;
import org.openrewrite.yaml.tree.Yaml;

/**
* @deprecated Likely better served by {@link org.openrewrite.kubernetes.trait.Traits}.
*/
@Deprecated
public class KubernetesVisitor<P> extends YamlVisitor<P> {

@Override
Expand Down
31 changes: 15 additions & 16 deletions src/main/java/org/openrewrite/kubernetes/UpdateKubernetesModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,26 @@ public class UpdateKubernetesModel<P> extends YamlIsoVisitor<P> {
public Yaml.Document visitDocument(Yaml.Document document, P p) {
Yaml.Document d = super.visitDocument(document, p);

KubernetesModel resource = new KubernetesModel(
randomId(),
getCursor().getMessage("apiVersion"),
getCursor().getMessage("kind"),
new KubernetesModel.Metadata(
getCursor().getMessage("namespace"),
getCursor().getMessage("name"),
getCursor().getMessage("annotations"),
getCursor().getMessage("labels")
)
);
if (resource.getApiVersion() != null && resource.getKind() != null) {
return d.withMarkers(document.getMarkers().addIfAbsent(resource));
} else {
return d;
if (getCursor().<String>getMessage("apiVersion") != null &&
getCursor().<String>getMessage("kind") != null) {
KubernetesModel kubernetesModel = new KubernetesModel(
randomId(),
getCursor().getMessage("apiVersion"),
getCursor().getMessage("kind"),
new KubernetesModel.Metadata(
getCursor().getMessage("namespace"),
getCursor().getMessage("name"),
getCursor().getMessage("annotations"),
getCursor().getMessage("labels")
));
return d.withMarkers(document.getMarkers().addIfAbsent(kubernetesModel));
}

return d;
}

@Override
public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, P p) {

String path = getPath();

if (entry.getValue() instanceof Yaml.Scalar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@
import lombok.Value;
import org.openrewrite.*;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.kubernetes.tree.K8S;
import org.openrewrite.kubernetes.trait.KubernetesResource;
import org.openrewrite.kubernetes.trait.Traits;
import org.openrewrite.marker.SearchResult;
import org.openrewrite.yaml.JsonPathMatcher;
import org.openrewrite.yaml.YamlIsoVisitor;
import org.openrewrite.yaml.tree.Yaml;

import java.util.concurrent.atomic.AtomicBoolean;

import static java.util.Objects.requireNonNull;

@Value
@EqualsAndHashCode(callSuper = false)
public class FindResourceMissingConfiguration extends Recipe {
Expand Down Expand Up @@ -57,29 +63,26 @@ public String getDescription() {
return "Find Kubernetes resources with missing configuration.";
}


@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
YamlIsoVisitor<ExecutionContext> visitor = new YamlIsoVisitor<ExecutionContext>() {
@Override
public Yaml.Document visitDocument(Yaml.Document document, ExecutionContext ctx) {
Yaml.Block b = (Yaml.Block) visit(document.getBlock(), ctx, getCursor());
boolean inKind = resourceKind == null || K8S.inKind(resourceKind, getCursor());
if (inKind && !"true".equals(getCursor().getMessage(FindResourceMissingConfiguration.class.getSimpleName()))) {
return SearchResult.found(document.withBlock(b));
}
return document;
}
TreeVisitor<? extends Tree, ExecutionContext> kubernetesResourceVisitor = Traits.kubernetesResource(resourceKind)
.asVisitor((KubernetesResource resource, ExecutionContext ctx) -> {
AtomicBoolean pathFound = new AtomicBoolean(false);
new YamlIsoVisitor<AtomicBoolean>() {
@Override
public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, AtomicBoolean bool) {
if (new JsonPathMatcher(configurationPath).matches(getCursor())) {
bool.set(true);
}
return bool.get() ? entry : super.visitMappingEntry(entry, bool);
}
}.visitNonNull(resource.getTree(), pathFound, requireNonNull(resource.getCursor().getParent()));
return pathFound.get() ? resource.getTree() : SearchResult.found(resource.getTree());
});

@Override
public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionContext ctx) {
if (K8S.firstEnclosingEntryMatching(configurationPath, getCursor()).isPresent()) {
getCursor().putMessageOnFirstEnclosing(Yaml.Document.class,
FindResourceMissingConfiguration.class.getSimpleName(), "true");
}
return super.visitMappingEntry(entry, ctx);
}
};
return fileMatcher != null ? Preconditions.check(new FindSourceFiles(fileMatcher), visitor) : visitor;
if (fileMatcher != null) {
return Preconditions.check(new FindSourceFiles(fileMatcher), kubernetesResourceVisitor);
}
return kubernetesResourceVisitor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.kubernetes.trait;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.Cursor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.kubernetes.UpdateKubernetesModel;
import org.openrewrite.kubernetes.tree.KubernetesModel;
import org.openrewrite.trait.SimpleTraitMatcher;
import org.openrewrite.trait.Trait;
import org.openrewrite.yaml.tree.Yaml;

@Value
public class KubernetesResource implements Trait<Yaml.Document> {

Cursor cursor;
KubernetesModel model;

@Value
@EqualsAndHashCode(callSuper = false)
public static class Matcher extends SimpleTraitMatcher<KubernetesResource> {

@Nullable
String kind;

@Override
protected @Nullable KubernetesResource test(Cursor cursor) {
Object value = cursor.getValue();
if (value instanceof Yaml.Document) {
return new UpdateKubernetesModel<ExecutionContext>()
.visitNonNull((Yaml.Document) value, new InMemoryExecutionContext(), cursor.getParent())
.getMarkers()
.findFirst(KubernetesModel.class)
.filter(model -> kind == null || kind.equals(model.getKind()))
.map(kubernetesModel -> new KubernetesResource(cursor, kubernetesModel))
.orElse(null);
}
return null;
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/org/openrewrite/kubernetes/trait/Traits.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.kubernetes.trait;

import org.openrewrite.internal.lang.Nullable;

public class Traits {

private Traits() {
}

public static KubernetesResource.Matcher kubernetesResource(@Nullable String kind) {
return new KubernetesResource.Matcher(kind);
}
}
31 changes: 16 additions & 15 deletions src/main/java/org/openrewrite/kubernetes/tree/K8S.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@
import lombok.With;
import lombok.experimental.FieldDefaults;
import org.openrewrite.Cursor;
import org.openrewrite.Tree;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.kubernetes.resource.ResourceLimit;
import org.openrewrite.marker.Marker;
import org.openrewrite.yaml.JsonPathMatcher;
import org.openrewrite.yaml.tree.Yaml;

Expand All @@ -35,8 +33,11 @@
import static java.util.Collections.emptySet;
import static org.openrewrite.Tree.randomId;

public interface K8S extends Marker {

/**
* @deprecated Likely better served by {@link org.openrewrite.kubernetes.trait.Traits}.
*/
@Deprecated
public interface K8S {

static boolean inKind(String kind, Cursor cursor) {
Yaml.Document doc = cursor.firstEnclosing(Yaml.Document.class);
Expand Down Expand Up @@ -210,7 +211,7 @@ static Optional<Cursor> firstEnclosingEntryMatching(JsonPathMatcher jsonPath, @N
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Resource implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -222,7 +223,7 @@ class Resource implements K8S {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Metadata implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -248,7 +249,7 @@ public static boolean isMetadata(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Annotations implements K8S {
@EqualsAndHashCode.Include
Expand Down Expand Up @@ -282,7 +283,7 @@ public boolean valueMatches(String name, Pattern regex, Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Labels implements K8S {
@EqualsAndHashCode.Include
Expand Down Expand Up @@ -312,7 +313,7 @@ public boolean valueMatches(String name, Pattern regex, Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Pod implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -326,7 +327,7 @@ public static boolean inSpec(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Containers implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -343,7 +344,7 @@ public static boolean isImageName(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class InitContainers implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -356,7 +357,7 @@ public static boolean inInitContainerSpec(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class ResourceLimits implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -380,7 +381,7 @@ public static boolean inRequests(String type, Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Service implements K8S {
@EqualsAndHashCode.Include
Expand All @@ -406,7 +407,7 @@ public static boolean inExternalIPs(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class Ingress implements K8S {
@EqualsAndHashCode.Include
Expand Down Expand Up @@ -434,7 +435,7 @@ public static boolean isDisallowHttpConfigured(Cursor cursor) {
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = false)
@EqualsAndHashCode(callSuper = false)
@Data
class RBAC implements K8S {
@EqualsAndHashCode.Include
Expand Down
Loading

0 comments on commit b711be6

Please sign in to comment.