Skip to content

Commit

Permalink
Increase code coverage in swatch producer aws
Browse files Browse the repository at this point in the history
  • Loading branch information
Sgitario committed Oct 6, 2023
1 parent fdbfaa6 commit a39cb05
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,10 @@
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import java.util.List;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@QuarkusTest
@Tag("integration")
class ContractsHttpEndpointIntegrationTest {
class ContractsHttpEndpointTest {

@InjectMock ContractService contractService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@

import lombok.Getter;

@Getter
public class AwsDimensionNotConfiguredException extends AwsProducerException {
@Getter private final String productId;
@Getter private final String uom;
private final String productId;
private final String uom;

public AwsDimensionNotConfiguredException(String productId, String uom) {
super(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@

import lombok.Getter;

@Getter
public class AwsUnprocessedRecordsException extends AwsProducerException {

@Getter private final int count;
private final int count;

public AwsUnprocessedRecordsException(int count) {
super(ErrorCode.AWS_UNPROCESSED_RECORDS_ERROR, String.format("count=%d", count));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
import com.redhat.swatch.aws.openapi.model.Errors;
import com.redhat.swatch.clients.swatch.internal.subscription.api.resources.ApiException;
import jakarta.ws.rs.core.Response;
import lombok.Getter;

@Getter
public class DefaultApiException extends ApiException {

private final transient Errors errors;
Expand All @@ -32,8 +34,4 @@ public DefaultApiException(Response response, Errors errors) {
super(response);
this.errors = errors;
}

public Errors getErrors() {
return this.errors;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import lombok.Getter;

@Getter
public enum ErrorCode {
AWS_UNPROCESSED_RECORDS_ERROR(1000, "Some AWS UsageRecords were not processed"),
AWS_DIMENSION_NOT_CONFIGURED(1001, "Aws Dimension not configured"),
Expand All @@ -33,8 +34,8 @@ public enum ErrorCode {

private static final String CODE_PREFIX = "SWATCHAWS";

@Getter private final String code;
@Getter private final String description;
private final String code;
private final String description;

ErrorCode(int intCode, String description) {
this.code = CODE_PREFIX + intCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import com.redhat.swatch.aws.exception.AwsMissingCredentialsException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -41,13 +42,14 @@
public class AwsCredentialsLookup {

private final Map<String, ProfileCredentialsProvider> awsCredentialMap = new HashMap<>();
private final ProfileFile profileFile = ProfileFile.defaultProfileFile();

@Inject ProfileFile profileFile;

public synchronized AwsCredentialsProvider getCredentialsProvider(String awsSellerAccount) {
return awsCredentialMap.computeIfAbsent(awsSellerAccount, this::createCredentialsFromProfile);
}

public ProfileCredentialsProvider createCredentialsFromProfile(String awsSellerAccount) {
private ProfileCredentialsProvider createCredentialsFromProfile(String awsSellerAccount) {
// NOTE: it is useful to do this check here, because it allows us to catch missing credentials
// in a predictable way.
if (profileFile.profile(awsSellerAccount).isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Red Hat trademarks are not licensed under GPLv3. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.swatch.aws.files;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import software.amazon.awssdk.profiles.ProfileFile;

@Dependent
public class ProfileFileConfiguration {
@ApplicationScoped
@Produces
public ProfileFile defaultProfileFile() {
return ProfileFile.defaultProfileFile();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class KafkaResource implements KafkaApi {
}

@Override
public void kakfaSeekPosition(KafkaSeekPosition position) throws ProcessingException {
public void kafkaSeekPosition(KafkaSeekPosition position) throws ProcessingException {
var seekHelperPosition =
switch (position) {
case BEGINNING -> KafkaSeekHelper.KafkaSeekPosition.BEGINNING;
Expand All @@ -46,7 +46,7 @@ public void kakfaSeekPosition(KafkaSeekPosition position) throws ProcessingExcep
}

@Override
public void kakfaSeekTimestamp(String timestamp) throws ProcessingException {
public void kafkaSeekTimestamp(String timestamp) throws ProcessingException {
kafkaSeekHelper.seekToTimestamp(OffsetDateTime.parse(timestamp));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import org.jboss.logmanager.ExtHandler;

// This is a copy because quarkus's stuff is package protected. Delete once
// https://github.com/quarkiverse/quarkus-logging-splunk/pull/111 is merged
// https://github.com/quarkiverse/quarkus-logging-splunk/pull/211 is merged
public class QuarkusHecErrorCallback implements ErrorCallback {
Boolean consoleEnabled;

Expand Down
8 changes: 4 additions & 4 deletions swatch-producer-aws/src/main/resources/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ paths:
schema:
$ref: '#/components/schemas/KafkaSeekPosition'
responses:
'202':
'204':
description: "Kafka queue seeked successfully for all partitions."
'400':
$ref: '#/components/responses/BadRequest'
Expand All @@ -51,7 +51,7 @@ paths:
$ref: '#/components/responses/ResourceNotFound'
'500':
$ref: '#/components/responses/InternalServerError'
operationId: kakfaSeekPosition
operationId: kafkaSeekPosition
description: >
Seek the kafka consumer manually to the specified position (for
debugging/support purposes)
Expand All @@ -66,7 +66,7 @@ paths:
schema:
type: string
responses:
'202':
'204':
description: "Kafka queue seeked successfully for all partitions."
'400':
$ref: '#/components/responses/BadRequest'
Expand All @@ -76,7 +76,7 @@ paths:
$ref: '#/components/responses/ResourceNotFound'
'500':
$ref: '#/components/responses/InternalServerError'
operationId: kakfaSeekTimestamp
operationId: kafkaSeekTimestamp
description: >
Seek the kafka consumer manually to the specified timestamp (for
debugging/support purposes).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,35 @@
*/
package com.redhat.swatch.aws;

import static io.restassured.RestAssured.given;

import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.Assert;
import org.junit.jupiter.api.Disabled;
import io.restassured.http.ContentType;
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Disabled("This placeholder test shows how to setup an integration test w/ DB & Kafka")
@QuarkusTest
@QuarkusTestResource(value = PostgresResource.class, restrictToAnnotatedClass = true)
@QuarkusTestResource(value = KafkaResource.class, restrictToAnnotatedClass = true)
@Tag("integration")
class TestContainerTest {
class BillableUsageResourceIT {

@Test
void testContainersStarting() {
Assert.assertTrue(true);
void testSubmitBillableUsage() {
given()
.contentType(ContentType.JSON)
.body(
"""
{
"sla": "Standard",
"usage": "Development/Test",
"billingProvider": "aws"
}
""")
.post("/api/swatch-producer-aws/internal/aws/billable_usage")
.then()
.statusCode(HttpStatus.SC_NO_CONTENT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ public class KafkaResource implements QuarkusTestResourceLifecycleManager {

static KafkaContainer kafka =
new KafkaContainer(
DockerImageName.parse("quay.io/cloudservices/cp-kafka")
.asCompatibleSubstituteFor("confluentinc/cp-kafka"));
DockerImageName.parse("quay.io/cloudservices/cp-kafka")
.asCompatibleSubstituteFor("confluentinc/cp-kafka"))
// SMELL: Workaround for https://github.com/testcontainers/testcontainers-java/issues/7539
// This is because testcontainers randomly fails to start a container when using Podman
// socket.
.withStartupAttempts(3);

@Override
public Map<String, String> start() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Red Hat trademarks are not licensed under GPLv3. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.swatch.aws;

import static io.restassured.RestAssured.post;

import com.redhat.swatch.aws.openapi.model.KafkaSeekPosition;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import java.time.OffsetDateTime;
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

@QuarkusTest
@QuarkusTestResource(value = PostgresResource.class, restrictToAnnotatedClass = true)
@QuarkusTestResource(value = KafkaResource.class, restrictToAnnotatedClass = true)
@Tag("integration")
class KafkaResourceIT {

@ParameterizedTest
@EnumSource(KafkaSeekPosition.class)
void testKafkaSeekPosition(KafkaSeekPosition position) {
post(basePath() + "/kafka_seek_position?position=" + position.toString())
.then()
.statusCode(HttpStatus.SC_NO_CONTENT);
}

@Test
void testKafkaSeekTimestamp() {
post(basePath() + "/kafka_seek_timestamp?timestamp=" + OffsetDateTime.now())
.then()
.statusCode(HttpStatus.SC_NO_CONTENT);
}

private String basePath() {
return "/api/swatch-producer-aws/internal";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Red Hat trademarks are not licensed under GPLv3. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.swatch.aws.files;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import com.redhat.swatch.aws.exception.AwsMissingCredentialsException;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.profiles.Profile;
import software.amazon.awssdk.profiles.ProfileFile;

@QuarkusTest
class AwsCredentialsLookupTest {
private static final String AWS_SELLER_ACCOUNT = "123";

@InjectMock ProfileFile mockProfileFile;
@Inject AwsCredentialsLookup lookup;

@Test
void testGetCredentialsProviderShouldThrowAwsMissingCredentialsException() {
givenUnknownAwsSellerAccount();
assertThrows(AwsMissingCredentialsException.class, this::whenGetCredentialsProvider);
}

@Test
void testGetCredentialsProviderShouldReturnProvider() {
givenKnownAwsSellerAccount();
AwsCredentialsProvider provider = whenGetCredentialsProvider();
assertTrue(provider instanceof ProfileCredentialsProvider);
}

private void givenUnknownAwsSellerAccount() {
when(mockProfileFile.profile(AWS_SELLER_ACCOUNT)).thenReturn(Optional.empty());
}

private void givenKnownAwsSellerAccount() {
when(mockProfileFile.profile(AWS_SELLER_ACCOUNT))
.thenReturn(Optional.of(Profile.builder().name("any").properties(Map.of()).build()));
}

private AwsCredentialsProvider whenGetCredentialsProvider() {
return lookup.getCredentialsProvider(AWS_SELLER_ACCOUNT);
}
}

0 comments on commit a39cb05

Please sign in to comment.