Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for custom Api Versions in informers (#639) #713

Merged
merged 2 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,17 @@
*/
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
private final Pattern customVersionParser = Pattern.compile("(V[a-z1-9]+)[A-Z]+[a-zA-Z0-9]+");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you get this regex from somewhere or have you created it?

I saw that you said this are valid:

  • V1MySettings
  • V1alpha1Operation

what about:

  • Vtest1Operation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually created it myself based on all the CRDs I know from my previous experiences but looking slightly more for references, I just found this one: https://github.com/kubernetes/apimachinery/blob/master/pkg/util/version/version.go#L38

Do you think we should use it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any update @n0tl3ss ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @cambierr can you update the PR with the regex that you have mentioned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, done!


public ModelMapper() {
initApiGroupMap();
initApiVersionList();
Expand Down Expand Up @@ -85,17 +93,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 +137,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{}
}
Loading