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

feat: fixes related to DSP conformance #4544

Merged
merged 1 commit into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -488,6 +488,7 @@ public Stream<? extends Arguments> provideArguments(ExtensionContext extensionCo
.counterPartyAddress("http://any")
.consumerPid("consumerPid")
.providerPid("providerPid")
.policy(Policy.Builder.newInstance().build())
.build(), PROVIDER, OFFERED),
Arguments.of(verified, ContractAgreementVerificationMessage.Builder.newInstance()
.protocol("protocol")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,15 @@ private boolean processRequesting(ContractNegotiation negotiation) {
}

/**
* Processes {@link ContractNegotiation} in state ACCEPTING. Tries to send a dummy contract agreement to
* the respective provider in order to approve the last offer sent by the provider. If this succeeds, the
* ContractNegotiation is transitioned to state ACCEPTED. Else, it is transitioned to ACCEPTING
* for a retry.
* Processes {@link ContractNegotiation} in state ACCEPTING. If the dispatch succeeds, the
* ContractNegotiation is transitioned to state ACCEPTED. Else, it is transitioned to ACCEPTING for a retry.
*
* @return true if processed, false otherwise
*/
@WithSpan
private boolean processAccepting(ContractNegotiation negotiation) {
var messageBuilder = ContractNegotiationEventMessage.Builder.newInstance().type(ACCEPTED);

messageBuilder.policy(negotiation.getLastContractOffer().getPolicy());
return dispatch(messageBuilder, negotiation, Object.class)
.onSuccess((n, result) -> transitionToAccepted(n))
.onFailure((n, throwable) -> transitionToAccepting(n))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.edc.connector.controlplane.contract.spi.negotiation.store.ContractNegotiationStore;
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement;
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreementVerificationMessage;
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractNegotiationEventMessage;
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation;
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationStates;
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest;
Expand Down Expand Up @@ -210,12 +211,16 @@ void requesting_shouldSendMessageWithId_whenCorrelationIdIsNull_toSupportOldProt
void accepting_shouldSendAcceptedMessageAndTransitionToApproved() {
var negotiation = contractNegotiationBuilder().state(ACCEPTING.code()).contractOffer(contractOffer()).build();
when(store.nextNotLeased(anyInt(), stateIs(ACCEPTING.code()))).thenReturn(List.of(negotiation)).thenReturn(emptyList());
when(dispatcherRegistry.dispatch(any(), any())).thenReturn(completedFuture(StatusResult.success("any")));

var captor = ArgumentCaptor.forClass(ContractNegotiationEventMessage.class);
when(dispatcherRegistry.dispatch(any(), captor.capture())).thenReturn(completedFuture(StatusResult.success("any")));
when(store.findById(negotiation.getId())).thenReturn(negotiation);

manager.start();

await().untilAsserted(() -> {
var message = captor.getValue();
assertThat(message.getPolicy()).isNotNull();
verify(store).save(argThat(p -> p.getState() == ACCEPTED.code()));
verify(dispatcherRegistry, only()).dispatch(any(), any());
verify(listener).accepted(any());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ public JsonObjectToPolicyTransformer(ParticipantIdMapper participantIdMapper) {
.error("Invalid type for ODRL policy, should be one of [%s, %s, %s]".formatted(ODRL_POLICY_TYPE_SET, ODRL_POLICY_TYPE_OFFER, ODRL_POLICY_TYPE_AGREEMENT))
.report();
return null;
} else if (policyType == PolicyType.CONTRACT) {
if (object.get(ODRL_ASSIGNEE_ATTRIBUTE) == null) {
context.problem()
.missingProperty()
.property(ODRL_ASSIGNEE_ATTRIBUTE)
.report();
return null;
}

if (object.get(ODRL_ASSIGNER_ATTRIBUTE) == null) {
context.problem()
.missingProperty()
.property(ODRL_ASSIGNER_ATTRIBUTE)
.report();
return null;
}
}

builder.type(policyType);
Expand All @@ -94,8 +110,10 @@ public JsonObjectToPolicyTransformer(ParticipantIdMapper participantIdMapper) {
case ODRL_PROHIBITION_ATTRIBUTE -> v -> builder.prohibitions(transformArray(v, Prohibition.class, context));
case ODRL_OBLIGATION_ATTRIBUTE -> v -> builder.duties(transformArray(v, Duty.class, context));
case ODRL_TARGET_ATTRIBUTE -> v -> builder.target(transformString(v, context));
case ODRL_ASSIGNER_ATTRIBUTE -> v -> builder.assigner(participantIdMapper.fromIri(transformString(v, context)));
case ODRL_ASSIGNEE_ATTRIBUTE -> v -> builder.assignee(participantIdMapper.fromIri(transformString(v, context)));
case ODRL_ASSIGNER_ATTRIBUTE ->
v -> builder.assigner(participantIdMapper.fromIri(transformString(v, context)));
case ODRL_ASSIGNEE_ATTRIBUTE ->
v -> builder.assignee(participantIdMapper.fromIri(transformString(v, context)));
case ODRL_PROFILE_ATTRIBUTE -> v -> builder.profiles(transformProfile(v));
default -> v -> builder.extensibleProperty(key, transformGenericProperty(v, context));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ void transform_differentPolicyTypes_returnPolicy(String type, PolicyType policyT
var policy = jsonFactory.createObjectBuilder()
.add(CONTEXT, JsonObject.EMPTY_JSON_OBJECT)
.add(TYPE, type)
.add(ODRL_ASSIGNEE_ATTRIBUTE, "assignee")
.add(ODRL_ASSIGNER_ATTRIBUTE, "assigner")
.build();

var result = transformer.transform(TestInput.getExpanded(policy), context);
Expand Down Expand Up @@ -179,6 +181,8 @@ void shouldGetTypeFromContext_whenSet() {

var policy = jsonFactory.createObjectBuilder()
.add(ODRL_TARGET_ATTRIBUTE, TARGET)
.add(ODRL_ASSIGNEE_ATTRIBUTE, "assignee")
.add(ODRL_ASSIGNER_ATTRIBUTE, "assigner")
.build();

var result = transformer.transform(TestInput.getExpanded(policy), context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private <T> StatusResult<T> handleResponse(Response response, String protocol, C
} else {
var stringBody = Optional.ofNullable(responseBody)
.map(this::asString)
.orElse("Response body is null");
.orElse("Response body is null. Error code: " + response.code());

var status = response.code() >= 400 && response.code() < 500 ? FATAL_ERROR : ERROR_RETRY;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public <I extends RemoteMessage, R> Response updateResource(PostDspRequest<I, R>
});

if (inputTransformation.failed()) {
monitor.debug(() -> "DSP: Transformation failed: %s".formatted(validation.getFailureMessages()));
monitor.debug(() -> "DSP: Transformation failed: %s".formatted(inputTransformation.getFailureMessages()));
return type(request.getErrorType()).processId(request.getProcessId()).badRequest();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractNegotiationEventMessage;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -52,6 +53,7 @@ void transform() {
.consumerPid("consumerPid")
.providerPid("providerPid")
.counterPartyAddress("https://test.com")
.policy(Policy.Builder.newInstance().build())
.type(ACCEPTED)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import static java.lang.String.format;
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation.Type.CONSUMER;
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation.Type.PROVIDER;
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationStates.FINALIZED;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;

/**
Expand Down Expand Up @@ -190,7 +191,7 @@ public void transitionRequesting() {
if (Type.PROVIDER == type) {
throw new IllegalStateException("Provider processes have no REQUESTING state");
}
transition(ContractNegotiationStates.REQUESTING, ContractNegotiationStates.REQUESTING, ContractNegotiationStates.INITIAL);
transition(ContractNegotiationStates.REQUESTING, ContractNegotiationStates.REQUESTING, ContractNegotiationStates.OFFERED, ContractNegotiationStates.INITIAL);
}

/**
Expand All @@ -209,7 +210,7 @@ public void transitionRequested() {
*/
public void transitionOffering() {
if (CONSUMER == type) {
throw new IllegalStateException("Provider processes have no OFFERING state");
throw new IllegalStateException("Consumer processes have no OFFERING state");
}

transition(ContractNegotiationStates.OFFERING, ContractNegotiationStates.OFFERING, ContractNegotiationStates.OFFERED, ContractNegotiationStates.REQUESTED);
Expand All @@ -233,7 +234,7 @@ public void transitionAccepting() {
if (Type.PROVIDER == type) {
throw new IllegalStateException("Provider processes have no ACCEPTING state");
}
transition(ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.REQUESTED);
transition(ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.REQUESTED, ContractNegotiationStates.OFFERED);
}

/**
Expand Down Expand Up @@ -301,7 +302,7 @@ public void transitionFinalizing() {
* Transition to state FINALIZED.
*/
public void transitionFinalized() {
transition(ContractNegotiationStates.FINALIZED, ContractNegotiationStates.FINALIZED, ContractNegotiationStates.FINALIZING, ContractNegotiationStates.AGREED, ContractNegotiationStates.VERIFIED);
transition(FINALIZED, FINALIZED, ContractNegotiationStates.FINALIZING, ContractNegotiationStates.AGREED, ContractNegotiationStates.VERIFIED);
}

/**
Expand All @@ -310,7 +311,7 @@ public void transitionFinalized() {
* @return true if the negotiation can be terminated, false otherwise
*/
public boolean canBeTerminated() {
return true;
return FINALIZED.code() != state;
}

/**
Expand Down
Loading
Loading