Skip to content

Commit

Permalink
Fix fabric8io#1804: Unable to create Template on OCP4
Browse files Browse the repository at this point in the history
    Modified BackwardCompatibilityInterceptor for handling /oapi
    failures in case of OpenShift
  • Loading branch information
rohanKanojia committed Jan 16, 2020
1 parent 403a6c5 commit 3b2a217
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 4.7-SNAPSHOT
#### Bugs
* `Quantity.getAmountInBytes()` should be able to handle negative exponents
* Fix #1805: Unable to create Template on OCP4

#### Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class BackwardsCompatibilityInterceptor implements Interceptor {
private static final Pattern NAMESPACED_URL_PATTERN = Pattern.compile("[^ ]+/apis/(" + NAME_REGEX + ")/(" + NAME_REGEX + ")/namespaces/" + NAME_REGEX + "/(" + NAME_REGEX + ")[^ ]*");
private static final Map<ResourceKey, ResourceKey> notFoundTransformations = new HashMap<>();
private static final Map<ResourceKey, ResourceKey> badRequestTransformations = new HashMap<>();
private static final Map<String, ResourceKey> openshiftOAPITransformations = new HashMap<>();

private static final Map<Integer, Map<ResourceKey, ResourceKey>> responseCodeToTransformations = new HashMap<>();

Expand Down Expand Up @@ -107,17 +108,33 @@ public int hashCode() {
notFoundTransformations.put(new ResourceKey("ClusterRoleBinding", "clusterrolebindings", "rbac.authorization.k8s.io", "v1"), new ResourceKey("ClusterRoleBinding", "clusterrolebindings", "rbac.authorization.k8s.io", "v1beta1"));
notFoundTransformations.put(new ResourceKey("ClusterRole", "clusterroles", "rbac.authorization.k8s.io", "v1"), new ResourceKey("ClusterRole", "clusterroles", "rbac.authorization.k8s.io", "v1beta1"));
notFoundTransformations.put(new ResourceKey("CronJob", "cronjobs", "batch", "v1beta1"), new ResourceKey("CronJob", "cronjob", "batch", "v2alpha1"));
notFoundTransformations.put(new ResourceKey("Template", "template", "", "v1"), new ResourceKey("Template", "template", "template.openshift.io", "v1"));

badRequestTransformations.put(new ResourceKey("Deployment", "deployments", "apps", "v1beta1"), new ResourceKey("Deployment", "deployments", "extensions", "v1beta1"));

responseCodeToTransformations.put(400, badRequestTransformations);
responseCodeToTransformations.put(404, notFoundTransformations);

/**
* OpenShift versions prior to 3.10 use the /oapi endpoint for Openshift specific resources.
* However, since 3.10 /apis/{group} is being used. This has been removed completely in 4.x
* versions of OpenShift. Hence, this code is to handle those cases.
*/
openshiftOAPITransformations.put("routes", new ResourceKey("Route", "routes", "route.openshift.io", "v1"));
openshiftOAPITransformations.put("templates", new ResourceKey("Template", "templates", "template.openshift.io", "v1"));
openshiftOAPITransformations.put("buildconfigs", new ResourceKey("BuildConfig", "buildconfigs", "build.openshift.io", "v1"));
openshiftOAPITransformations.put("deploymentconfigs", new ResourceKey("DeploymentConfig", "deploymentconfigs", "apps.openshift.io", "v1"));
openshiftOAPITransformations.put("imagestreams", new ResourceKey("ImageStream", "imagestreams", "image.openshift.io", "v1"));
openshiftOAPITransformations.put("imagestreamtags", new ResourceKey("ImageStream", "imagestreamtags", "image.openshift.io", "v1"));
openshiftOAPITransformations.put("securitycontextconstraints", new ResourceKey("SecurityContextConstraints", "securitycontextconstraints", "security.openshift.io", "v1"));
}

public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (!response.isSuccessful() && responseCodeToTransformations.keySet().contains(response.code())) {
if (isDeprecatedOpenshiftOapiRequest(request)) {
return handleOpenshiftOapiRequests(request, response, chain);
} else if (!response.isSuccessful() && responseCodeToTransformations.keySet().contains(response.code())) {
String url = request.url().toString();
Matcher matcher = getMatcher(url);
ResourceKey key = getKey(matcher);
Expand All @@ -129,21 +146,7 @@ public Response intercept(Chain chain) throws IOException {
.replace(matcher.start(API_GROUP), matcher.end(API_GROUP), target.group)
.toString();

Request.Builder newRequest = request.newBuilder()
.url(newUrl);

Buffer buffer = new Buffer();
if (request.body() != null && !request.method().equalsIgnoreCase(PATCH)) {
request.body().writeTo(buffer);
Object object = Serialization.unmarshal(buffer.inputStream());
if (object instanceof HasMetadata) {
HasMetadata h = (HasMetadata) object;
h.setApiVersion(target.group + "/" + target.version);
newRequest = newRequest.method(request.method(), RequestBody.create(OperationSupport.JSON, Serialization.asJson(h)));
}
}

return chain.proceed(newRequest.build());
return handleNewRequestAndProceed(request, newUrl, target, chain);
}
}
return response;
Expand All @@ -165,4 +168,48 @@ private static Matcher getMatcher(String url) {
private static ResourceKey getKey(Matcher m) {
return m != null ? new ResourceKey(null, m.group(PATH), m.group(API_GROUP), m.group(API_VERSION)) : null;
}

private static Response handleOpenshiftOapiRequests(Request request, Response response, Chain chain) throws IOException{
if (!response.isSuccessful()) {
String requestUrl = request.url().toString();
// handle case when /oapi is not available
String[] parts = requestUrl.split("/");
String resourcePath = parts[parts.length - 1];
ResourceKey target = openshiftOAPITransformations.get(resourcePath);
if (target != null) {
requestUrl = requestUrl.replace("/oapi", "/apis/" + target.getGroup());
return handleNewRequestAndProceed(request, requestUrl, target, chain);
}
}
return response;
}

private static Response handleNewRequestAndProceed(Request request, String newUrl, ResourceKey target, Chain chain) throws IOException {
Request.Builder newRequest = request.newBuilder()
.url(newUrl);

if (request.body() != null && !request.method().equalsIgnoreCase(PATCH)) {
try (Buffer buffer = new Buffer()) {
request.body().writeTo(buffer);

Object object = Serialization.unmarshal(buffer.inputStream());
if (object instanceof HasMetadata) {
HasMetadata h = (HasMetadata) object;
if (target != null) {
h.setApiVersion(target.group + "/" + target.version);
}
newRequest = newRequest.method(request.method(), RequestBody.create(OperationSupport.JSON, Serialization.asJson(h)));
}
}
}

return chain.proceed(newRequest.build());
}

private static boolean isDeprecatedOpenshiftOapiRequest(Request request) {
if (request != null && request.url() != null) {
return request.url().toString().contains("oapi");
}
return false;
}
}

0 comments on commit 3b2a217

Please sign in to comment.