Skip to content

Commit

Permalink
Merge branch 'main' into implement-registry-event-source
Browse files Browse the repository at this point in the history
  • Loading branch information
carlesarnal committed Oct 8, 2024
2 parents 44f1cd1 + f7a50d3 commit 94a179d
Show file tree
Hide file tree
Showing 342 changed files with 5,393 additions and 1,508 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ updates:
directory: "/python-sdk"
schedule:
interval: daily
- package-ecosystem: nuget
directory: "/go-sdk"
schedule:
interval: daily

- package-ecosystem: maven
directory: "/"
Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,27 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Enable port-forwarding
run: |
sudo apt-get -y install socat
- name: Setup Minikube-Kubernetes
uses: manusa/[email protected]
with:
minikube version: v1.28.0
kubernetes version: v1.25.0
github token: ${{ secrets.GITHUB_TOKEN }}
start args: '--force'

- name: Enable minikube ingress
run: |
minikube addons enable ingress
- name: Setup minikube tunnel
run: |
minikube tunnel &
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
Expand All @@ -49,7 +63,6 @@ jobs:
mkdir -p /tmp/coreutils-workaround
( cd /tmp/coreutils-workaround && mvn dependency:get -DremoteRepositories=https://repo1.maven.org/maven2 -Dartifact=com.github.java-json-tools:jackson-coreutils:2.0 )
- name: Run the tests in local mode
run: ./mvnw clean verify -P '!external_repos' -DskipOperatorTests=false -pl operator/controller -am

Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/qodana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ jobs:
name: Qodana
runs-on: ubuntu-latest
if: >
github.repository_owner == 'Apicurio' &&
!contains(github.event.*.labels.*.name, 'DO NOT MERGE') &&
github.event.pull_request.user.login != 'dependabot[bot]'
github.repository_owner == 'Apicurio' && contains(github.event.*.labels.*.name, 'QODANA')
permissions:
checks: write
contents: write
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/release-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,19 @@ jobs:
SKIP_TESTS: "true"
run: |
cd registry
./mvnw package --no-transfer-progress -Pnative -Dquarkus.native.container-build=true -Pprod -DskipTests=true
./mvnw package --no-transfer-progress -Pnative -Dquarkus.native.container-build=true -Pprod -DskipTests=true
- name: Build and Push Native image for testing
run: |
docker build --push -f ./distro/docker/target/docker/Dockerfile.native app/ \
cd registry
docker build --push -f ./distro/docker/target/docker/Dockerfile.native \
-t docker.io/apicurio/apicurio-registry-native:latest \
-t docker.io/apicurio/apicurio-registry-native:latest-release \
-t docker.io/apicurio/apicurio-registry-native:$RELEASE_VERSION \
-t quay.io/apicurio/apicurio-registry-native:latest \
-t quay.io/apicurio/apicurio-registry-native:latest-release \
-t quay.io/apicurio/apicurio-registry-native:$RELEASE_VERSION
-t quay.io/apicurio/apicurio-registry-native:$RELEASE_VERSION \
app/
- name: Google Chat Notification
if: ${{ failure() }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.apicurio.registry.storage.error.ArtifactNotFoundException;
import io.apicurio.registry.storage.error.RuleNotFoundException;
import io.apicurio.registry.storage.error.VersionNotFoundException;
import io.apicurio.registry.storage.impl.sql.RegistryContentUtils;
import io.apicurio.registry.types.ArtifactType;
import io.apicurio.registry.types.ContentTypes;
import io.apicurio.registry.types.Current;
Expand Down Expand Up @@ -104,7 +105,8 @@ protected ArtifactVersionMetaDataDto createOrUpdateArtifact(String artifactId, S
.map(dto -> ArtifactReference.builder().name(dto.getName()).groupId(dto.getGroupId())
.artifactId(dto.getArtifactId()).version(dto.getVersion()).build())
.collect(Collectors.toList());
final Map<String, TypedContent> resolvedReferences = storage.resolveReferences(parsedReferences);
final Map<String, TypedContent> resolvedReferences = RegistryContentUtils
.recursivelyResolveReferences(parsedReferences, storage::getContentByReference);
try {
ContentHandle schemaContent;
schemaContent = ContentHandle.create(schema);
Expand Down Expand Up @@ -175,8 +177,9 @@ protected ArtifactVersionMetaDataDto lookupSchema(String groupId, String artifac
.getArtifactVersionContent(groupId, artifactId, version);
TypedContent typedArtifactVersion = TypedContent
.create(artifactVersion.getContent(), artifactVersion.getContentType());
Map<String, TypedContent> artifactVersionReferences = storage
.resolveReferences(artifactVersion.getReferences());
Map<String, TypedContent> artifactVersionReferences = RegistryContentUtils
.recursivelyResolveReferences(artifactVersion.getReferences(),
storage::getContentByReference);
String dereferencedExistingContentSha = DigestUtils
.sha256Hex(artifactTypeProvider.getContentDereferencer()
.dereference(typedArtifactVersion, artifactVersionReferences)
Expand Down Expand Up @@ -215,7 +218,8 @@ protected Map<String, TypedContent> resolveReferences(List<SchemaReference> refe
return artifactReferenceDto;
}).collect(Collectors.toList());

resolvedReferences = storage.resolveReferences(referencesAsDtos);
resolvedReferences = RegistryContentUtils.recursivelyResolveReferences(referencesAsDtos,
storage::getContentByReference);

if (references.size() > resolvedReferences.size()) {
// There are unresolvable references, which is not allowed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.apicurio.registry.storage.dto.ArtifactVersionMetaDataDto;
import io.apicurio.registry.storage.dto.ContentWrapperDto;
import io.apicurio.registry.storage.dto.StoredArtifactVersionDto;
import io.apicurio.registry.storage.impl.sql.RegistryContentUtils;
import io.apicurio.registry.types.ArtifactType;
import io.apicurio.registry.types.VersionState;
import io.apicurio.registry.util.ArtifactTypeUtil;
Expand Down Expand Up @@ -47,8 +48,10 @@ public SchemaInfo getSchema(int id, String subject, String groupId) {
references = contentWrapper.getReferences();
}
TypedContent typedContent = TypedContent.create(contentHandle, contentType);
return converter.convert(contentHandle, ArtifactTypeUtil.determineArtifactType(typedContent, null,
storage.resolveReferences(references), factory), references);
return converter.convert(contentHandle,
ArtifactTypeUtil.determineArtifactType(typedContent, null, RegistryContentUtils
.recursivelyResolveReferences(references, storage::getContentByReference), factory),
references);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
package io.apicurio.registry.rest;

import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.UnauthorizedException;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFailedExceptionMapper implements ExceptionMapper<UnauthorizedException> {

@Inject
RegistryExceptionMapper exceptionMapperService;

public class AuthenticationFailedExceptionMapper implements ExceptionMapper<AuthenticationFailedException> {
@Override
public Response toResponse(AuthenticationFailedException exception) {
return Response.status(401).build();
public Response toResponse(UnauthorizedException exception) {
Response errorHttpResponse = exceptionMapperService.toResponse(exception);
return Response.status(401).entity(errorHttpResponse).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.slf4j.Logger;

/**
* TODO use v1 beans when appropriate (when handling REST API v1 calls)
Expand All @@ -19,9 +18,6 @@
@Provider
public class RegistryExceptionMapper implements ExceptionMapper<Throwable> {

@Inject
Logger log;

@Inject
CoreRegistryExceptionMapperService coreMapper;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,143 +1,10 @@
package io.apicurio.registry.rest.v2;

import io.apicurio.common.apps.config.Info;
import io.apicurio.registry.content.TypedContent;
import io.apicurio.registry.content.dereference.ContentDereferencer;
import io.apicurio.registry.content.refs.JsonPointerExternalReference;
import io.apicurio.registry.storage.RegistryStorage;
import io.apicurio.registry.storage.dto.ArtifactReferenceDto;
import io.apicurio.registry.types.Current;
import io.apicurio.registry.types.provider.ArtifactTypeUtilProvider;
import io.apicurio.registry.types.provider.ArtifactTypeUtilProviderFactory;
import io.apicurio.registry.utils.StringUtil;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.core.Context;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.slf4j.Logger;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractResourceImpl {

@Inject
Logger log;

@Inject
@Current
RegistryStorage storage;

@Inject
ArtifactTypeUtilProviderFactory factory;

@Context
HttpServletRequest request;

@ConfigProperty(name = "apicurio.apis.v2.base-href", defaultValue = "_")
@Info(category = "api", description = "API base href (URI)", availableSince = "2.5.0.Final")
String apiBaseHref;

/**
* Handle the content references based on the value of "dereference" - this can mean we need to fully
* dereference the content.
*
* @param dereference
* @param content
*/
protected TypedContent handleContentReferences(boolean dereference, String artifactType,
TypedContent content, List<ArtifactReferenceDto> references) {
// Dereference or rewrite references
if (!references.isEmpty() && dereference) {
ArtifactTypeUtilProvider artifactTypeProvider = factory.getArtifactTypeProvider(artifactType);
ContentDereferencer contentDereferencer = artifactTypeProvider.getContentDereferencer();
Map<String, TypedContent> resolvedReferences = storage.resolveReferences(references);
content = contentDereferencer.dereference(content, resolvedReferences);
}
return content;
}

/**
* Convert the list of references into a list of REST API URLs that point to the content. This means that
* we generate a REST API URL from the GAV (groupId, artifactId, version) information found in each
* reference.
*
* @param references
*/
protected Map<String, String> resolveReferenceUrls(List<ArtifactReferenceDto> references) {
Map<String, String> rval = new HashMap<>();
for (ArtifactReferenceDto reference : references) {
String resolvedReferenceUrl = resolveReferenceUrl(reference);
if (reference.getName().contains("#")) {
JsonPointerExternalReference jpRef = new JsonPointerExternalReference(reference.getName());
resolvedReferenceUrl = resolvedReferenceUrl + jpRef.getComponent();
}
if (resolvedReferenceUrl != null) {
rval.put(reference.getName(), resolvedReferenceUrl);
}
}
return rval;
}

/**
* Convert a single artifact reference to a REST API URL. This means that we generate a REST API URL from
* the GAV (groupId, artifactId, version) information found in the reference.
*
* @param reference
*/
protected String resolveReferenceUrl(ArtifactReferenceDto reference) {
URI baseHref = null;
try {
if (!"_".equals(apiBaseHref)) {
baseHref = new URI(apiBaseHref);
} else {
baseHref = getApiBaseHrefFromXForwarded(request);
if (baseHref == null) {
baseHref = getApiBaseHrefFromRequest(request);
}
}
} catch (URISyntaxException e) {
this.log.error("Error trying to determine the baseHref of the REST API.", e);
return null;
}

if (baseHref == null) {
this.log.warn("Failed to determine baseHref for the REST API.");
return null;
}

String path = String.format("/apis/registry/v2/groups/%s/artifacts/%s/versions/%s?references=REWRITE",
URLEncoder.encode(reference.getGroupId(), StandardCharsets.UTF_8),
URLEncoder.encode(reference.getArtifactId(), StandardCharsets.UTF_8),
URLEncoder.encode(reference.getVersion(), StandardCharsets.UTF_8));
return baseHref.resolve(path).toString();
}

/**
* Resolves a host name from the information found in X-Forwarded-Host and X-Forwarded-Proto.
*/
private static URI getApiBaseHrefFromXForwarded(HttpServletRequest request) throws URISyntaxException {
String fproto = request.getHeader("X-Forwarded-Proto");
String fhost = request.getHeader("X-Forwarded-Host");
if (!StringUtil.isEmpty(fproto) && !StringUtil.isEmpty(fhost)) {
return new URI(fproto + "://" + fhost);
} else {
return null;
}
}

/**
* Resolves a host name from the request information.
*/
private static URI getApiBaseHrefFromRequest(HttpServletRequest request) throws URISyntaxException {
String requestUrl = request.getRequestURL().toString();
URI requestUri = new URI(requestUrl);
return requestUri.resolve("/");
}

}
Loading

0 comments on commit 94a179d

Please sign in to comment.