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

Increase code coverage in swatch producer aws #2618

Closed
Closed
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
1 change: 1 addition & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ libraries["wiremock"] = "com.github.tomakehurst:wiremock-standalone:3.0.1"
libraries["awaitility"] = "org.awaitility:awaitility:4.2.0"
libraries["splunk-otel-agent"] = 'com.splunk:splunk-otel-javaagent:1.28.0'
libraries["testcontainers-postgresql"] = 'org.testcontainers:postgresql:1.19.1'
libraries["embeddedkafka"] = 'io.github.embeddedkafka:embedded-kafka_3:3.6.0'
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
3 changes: 2 additions & 1 deletion swatch-producer-aws/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ dependencies {
testImplementation 'io.rest-assured:rest-assured'
testImplementation 'org.mockito:mockito-junit-jupiter'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:kafka'
testImplementation 'org.testcontainers:postgresql'
testImplementation 'org.testcontainers:testcontainers'
testImplementation libraries["junit-jupiter"]
testImplementation libraries["wiremock"]
testImplementation project(':swatch-common-testcontainers')
testImplementation libraries["embeddedkafka"]
testImplementation 'org.apache.kafka:kafka-metadata:3.4.1'
}

compileJava.dependsOn tasks.openApiGenerate
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 @@ -20,27 +20,37 @@
*/
package com.redhat.swatch.aws;

import static org.testcontainers.shaded.org.awaitility.Awaitility.await;

import io.github.embeddedkafka.EmbeddedK;
import io.github.embeddedkafka.EmbeddedKafka;
import io.github.embeddedkafka.EmbeddedKafkaConfig;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import java.util.Collections;
import java.util.Map;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.utility.DockerImageName;

public class KafkaResource implements QuarkusTestResourceLifecycleManager {

static KafkaContainer kafka =
new KafkaContainer(
DockerImageName.parse("quay.io/cloudservices/cp-kafka")
.asCompatibleSubstituteFor("confluentinc/cp-kafka"));
private EmbeddedK kafka;

@Override
public Map<String, String> start() {
kafka.start();
return Collections.singletonMap("kafka.bootstrap.servers", kafka.getBootstrapServers());
kafka = EmbeddedKafka.start(EmbeddedKafkaConfig.defaultConfig());
await()
.until(() -> kafka.broker().brokerState() == org.apache.kafka.metadata.BrokerState.RUNNING);
return Collections.singletonMap(
"kafka.bootstrap.servers", "PLAINTEXT://localhost:" + kafka.config().kafkaPort());
}

@Override
public void stop() {
kafka.stop();
try {
if (kafka != null) {
kafka.stop(true);
kafka = null;
}
} catch (Exception ignored) {

}
}
}
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)
.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";
}
}
Loading