Skip to content

Commit

Permalink
Implement support for custom Api Versions in informers (#639) (#713)
Browse files Browse the repository at this point in the history
This adds the support of custom api versions to the informer library as discussed in #639

* Implement support for custom Api Versions in informers (#639)
* Update parsing regex to rely on the kubernetes core one
  • Loading branch information
cambierr authored Jul 19, 2024
1 parent 3cc85cd commit 7239adf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
import io.kubernetes.client.util.Strings;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
* This class is inspired by the implementation of the <a href="https://github.com/kubernetes-client/java/blob/release-13/util/src/main/java/io/kubernetes/client/util/ModelMapper.java">io.kubernetes.client.util.ModelMapper.java</a>.
Expand All @@ -38,12 +41,19 @@
*/
public class ModelMapper {

private static final Logger LOG = LoggerFactory.getLogger(ModelMapper.class);

// Model's api-group prefix to kubernetes api-group
private final Map<String, String> preBuiltApiGroups = new HashMap<>();

// Model's api-version midfix to kubernetes api-version
private final List<String> preBuiltApiVersions = new ArrayList<>();

// This allows parsing custom (not included in kubernetes core) api versions
// It is based on the kubernetes core one available at https://github.com/kubernetes/apimachinery/blob/master/pkg/util/version/version.go
// and is completed to be able to proceed to extraction from a java class name
private final Pattern customVersionParser = Pattern.compile("^\\s*(V(?:[0-9]+(?:\\.[0-9]+)*)(?:[a-z0-9]*)*)[A-Z]+[a-zA-Z0-9]*$");

public ModelMapper() {
initApiGroupMap();
initApiVersionList();
Expand Down Expand Up @@ -85,17 +95,37 @@ private void initApiVersionList() {
private Pair<String, String> getApiGroup(String name) {
return preBuiltApiGroups.entrySet().stream()
.filter(e -> name.startsWith(e.getKey()))
.map(e -> new MutablePair<String, String>(e.getValue(), name.substring(e.getKey().length())))
.map(e -> new MutablePair<>(e.getValue(), name.substring(e.getKey().length())))
.findFirst()
.orElse(new MutablePair<String, String>(null, name));
.orElse(new MutablePair<>(null, name));
}

private Pair<String, String> getApiVersion(String name) {
return preBuiltApiVersions.stream()
.filter(name::startsWith)
.map(v -> new MutablePair<String, String>(v.toLowerCase(), name.substring(v.length())))
.map(v -> new MutablePair<>(v, extractKind(v, name)))
.findFirst()
.orElse(new MutablePair<String, String>(null, name));
.orElseGet(() -> {
String version = tryGuessCustomApiVersion(name);
return new MutablePair<>(version, extractKind(version, name));
});
}

private String extractKind(String version, String name){
return version == null ? name : name.substring(version.length());
}

private String tryGuessCustomApiVersion(String name) {
var patternMatcher = customVersionParser.matcher(name);

if (patternMatcher.matches() && patternMatcher.groupCount() == 1) {
return patternMatcher.group(1);
}

// Warn the user to avoid wasted debug time (cfr https://github.com/micronaut-projects/micronaut-kubernetes/issues/639)
LOG.warn("Could not extract ApiVersion from entity {}", name);

return null;
}

/**
Expand All @@ -109,8 +139,9 @@ public GroupVersionKind getGroupVersionKindByClass(Class<? extends KubernetesObj
Pair<String, String> versionAndOther = getApiVersion(groupAndOther.getRight());

String group = Strings.nullToEmpty(groupAndOther.getLeft());
String version = versionAndOther.getLeft();
String version = versionAndOther.getLeft() == null ? null : versionAndOther.getLeft().toLowerCase();
String kind = versionAndOther.getRight();

return new GroupVersionKind(group, version, kind);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,15 @@ class ModelMapperSpec extends Specification {
it.kind == "ClusterRole"
}
}

def "it resolves custom api versions"() {
expect:
with(mapper.getGroupVersionKindByClass(V3CustomResource)) {
it.version == "v3"
it.group == ""
it.kind == "CustomResource"
}
}

static class V3CustomResource{}
}

0 comments on commit 7239adf

Please sign in to comment.