Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
9efc8fe
refactor(Update to include fares v2 data manager refs and tests):
br648 Aug 20, 2024
8e42038
refactor(Bumped GTFS-Lib version):
br648 Oct 18, 2024
c81ffe4
fix(Fixed merge conflicts):
br648 Jan 28, 2025
468a586
improvement(pom.xml): Bumped GTFS-lib version to lastest fares v2 dev…
br648 Jan 28, 2025
8f0474f
improvement(pom.xml): Bumped GTFS lib version
br648 Jan 31, 2025
b4deec9
improvement(pom.xml): Bumped GTFS-Lib version
br648 Feb 5, 2025
df16b7e
improvement(Unit test): Added a simple test to update a fare product
br648 Feb 6, 2025
7b446d1
fix(pom.xml): Removed unwanted GTFS lib dependency.
br648 Feb 6, 2025
fe4e278
improvement(EditorControllerTest.java): Updated fare product test to …
br648 Feb 7, 2025
0cff428
improvement(Fixed merge conflict):
br648 Jun 17, 2025
e9bc793
improvement(pom.xml): Updated the GTFS lib version
br648 Jun 17, 2025
88b5a79
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Jun 17, 2025
b42bd84
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Jul 4, 2025
d2df5ca
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Jul 15, 2025
6f6e617
improvement(Bumped GTFS-Lib version):
br648 Jul 31, 2025
bc3426f
improvement(Reverted gtfs-lib version): Newer version had breaking ch…
br648 Aug 1, 2025
14e116d
feat(Address changes in gtfs-lib): Merge stop areas into stops update
br648 Aug 1, 2025
3f867f9
improvement(GTFS-Lib version): Bumped to latest for merge stop areas
br648 Aug 5, 2025
9cd803c
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Aug 5, 2025
3b7d073
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Aug 7, 2025
f36adff
improvement(pom.xml): Bumped GTFS-Lib version to include entry in zip…
br648 Aug 11, 2025
adb8ebd
improvement(GTFS-Lib): Bumped version to include export for stop areas
br648 Aug 14, 2025
8c9091f
improvement(Bumped GTFS-Lib version):
br648 Aug 22, 2025
bb5b3fb
improvement(Bumped GTFS-Lib version):
br648 Aug 26, 2025
30f3fbf
improvement(Bumped GTFS-Lib version):
br648 Aug 27, 2025
78aa3f2
Merge pull request #632 from ibi-group/merge-stop-areas
br648 Aug 27, 2025
88ddcbe
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Oct 17, 2025
b8bedc3
improvement(maven.yml): Bumped node version from 20.x to 22.x
br648 Oct 17, 2025
4547839
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Nov 6, 2025
59ca852
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Dec 10, 2025
69bb184
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Dec 11, 2025
b77cbac
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Dec 17, 2025
0030941
improvement(pom.xml): Updated GTFS-Lib version
br648 Dec 22, 2025
969bbef
improvement(Updated the GTFS-Lib version): Latest version includes ne…
br648 Jan 20, 2026
75e9bec
improvement(GTFS-Lib version update and editor controller impl): GTFS…
br648 Jan 21, 2026
2382e77
improvement(EditorControllerTest.java): Updated test to include missi…
br648 Jan 21, 2026
cb0fd0c
improvement(FaresV2ValidationTest.java): Update unit test to include …
br648 Jan 21, 2026
c3e5004
Bump GTFS-lib version to include a bug fix
br648 Mar 5, 2026
8ed45ad
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Mar 9, 2026
79d30b4
Merge branch 'dev' into feature/DT-448-fares-v2
br648 Mar 30, 2026
0109e88
improvement(pom.xml): Bumped gtfs-lib version
br648 Apr 15, 2026
91c23c6
improvement(pom.xml): Bumped gtfs-lib version
br648 Apr 23, 2026
2fd2e4e
Merge pull request #600 from ibi-group/feature/DT-448-fares-v2
br648 Apr 23, 2026
1d32194
support new ignoreNonBlanks feature
miles-grant-ibigroup Apr 28, 2026
61edf76
update gtfs-lib
miles-grant-ibigroup May 4, 2026
661fe72
update gtfs-lib
miles-grant-ibigroup May 4, 2026
98928a9
test(FeedSourceController): Add feedSourceId to published version.
binh-dam-ibigroup May 13, 2026
d229f04
perf(FeedSourceSummary): Add feedSourceId filter to project 2nd lookup.
binh-dam-ibigroup May 13, 2026
62966a2
Merge pull request #650 from ibi-group/fix-project-list-perf
binh-dam-ibigroup May 20, 2026
8f73cb0
update gtfs lib
miles-grant-ibigroup May 27, 2026
489b305
Merge pull request #647 from ibi-group/interpolation-repair
miles-grant-ibigroup May 27, 2026
509d05f
fix(FeedSource): Upload public feeds to S3 when publishing project fe…
binh-dam-ibigroup May 28, 2026
3bc3218
refactor(PublishProjectFeedsJob): Reuse upload code, remove dead code.
binh-dam-ibigroup May 28, 2026
a9c059f
fix(S3Utils): Update S3 http URL scheme.
binh-dam-ibigroup May 28, 2026
f40e34f
improvement(Fixed merge conflicts):
br648 Jun 2, 2026
429d8cd
feat(FeedUpdater): Use separate extension AWS credentials from default.
binh-dam-ibigroup Jun 2, 2026
4350b01
refactor(MtcFeedResource): Move MTC S3 logic to this class.
binh-dam-ibigroup Jun 2, 2026
8585863
fix: Use MTC S3 client for FeedUpdater and MtcFeedResource.
binh-dam-ibigroup Jun 2, 2026
35176c2
fix(DataManager): Check extension bucket for FeedUpdater.
binh-dam-ibigroup Jun 2, 2026
6f8e042
fix(MtcFeedResource): Implement credential fallback.
binh-dam-ibigroup Jun 2, 2026
18b921f
refactor(MtcFeedResource): Remove redundant fallback.
binh-dam-ibigroup Jun 2, 2026
d23b7f8
refactor: Rename variables and cache s3wrapper.
binh-dam-ibigroup Jun 2, 2026
6378872
chore: Revert mtc change to server.yml.tmp.
binh-dam-ibigroup Jun 3, 2026
66fdbb5
refactor(FeedUpdater): Inline vars and fix JavaDoc.
binh-dam-ibigroup Jun 3, 2026
39e3af9
refactor(MtcFeedResource): Rename methods and fix JavaDoc.
binh-dam-ibigroup Jun 3, 2026
131d1cf
Revert "chore: Revert mtc change to server.yml.tmp."
binh-dam-ibigroup Jun 3, 2026
3f5dcea
chore(server.yml.tmp): Add comments for new config items.
binh-dam-ibigroup Jun 3, 2026
3f40fcd
perf(PublishProjectFeedsJob): Retrieve latest feed version only once.
binh-dam-ibigroup Jun 3, 2026
ba60959
fix(FeedSourceSummary): Add publishedVersionId.
binh-dam-ibigroup Jun 4, 2026
92a11c7
test(FeedSourceController): Test for new field.
binh-dam-ibigroup Jun 5, 2026
b3a9f2e
refactor: Fix JavaDoc and comments.
binh-dam-ibigroup Jun 5, 2026
7f138f0
perf(PublishProjectFeedsJob): Replace concats with chained appends.
binh-dam-ibigroup Jun 5, 2026
eeef16f
improvement(pom.xml): Updated GTFS-Lib version
br648 Jun 8, 2026
d569036
improvement(GTFS-lib and test updates): Newer GTFS-Lib to include upd…
br648 Jun 10, 2026
4a8777b
Merge pull request #653 from ibi-group/fix-source-summary
binh-dam-ibigroup Jun 11, 2026
66d5567
Merge pull request #652 from ibi-group/use-s3-for-public-feed-downloads
binh-dam-ibigroup Jun 11, 2026
4e3851e
update gtfs-lib
miles-grant-ibigroup Jun 19, 2026
6d1078b
chore(Bumped gtfs-lib version):
br648 Jun 19, 2026
ed19727
Merge branch 'fix-missing-fare-table' of https://github.com/ibi-group…
br648 Jun 19, 2026
cdc6f87
Merge pull request #654 from ibi-group/fix-missing-fare-table
miles-grant-ibigroup Jun 19, 2026
f0873d8
chore(Bump gtfs-lib version):
br648 Jun 23, 2026
56d9064
Updated GTFS lib version
br648 Jul 13, 2026
1342649
chore(Config update): disabled mtc extension by default
br648 Jul 14, 2026
81d0288
chore(config update): enabled mtc extension by default
br648 Jul 14, 2026
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
6 changes: 5 additions & 1 deletion configurations/test/server.yml.tmp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ modules:
gtfsapi:
enabled: true
load_on_fetch: false
# use_extension: mtc
use_extension: mtc
# update_frequency: 30 # in seconds
manager:
normalizeFieldTransformation:
Expand Down Expand Up @@ -74,8 +74,12 @@ extensions:
enabled: true
rtd_api: http://localhost:9876/
s3_bucket: bucket-name
### Uncomment and edit if the S3 region of the bucket above is different than application.data.s3_region.
# s3_region: us-west-2
s3_prefix: waiting/
s3_download_prefix: waiting/
### Uncomment and edit if separate credentials are needed to access the bucket above.
# s3_credentials_file: ~/.aws/credentials
transitland:
enabled: true
api: https://transit.land/api/v1/feeds
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@
<groupId>com.github.ibi-group</groupId>
<artifactId>gtfs-lib</artifactId>
<!-- Latest dev-flex build on jitpack.io -->
<version>dbbf3d166cf31fc9dae490ef4b8db42ec436f743</version>
<version>9a3ac87a9fdb96a1516e5badf3bca6071fb6aca7</version>
<!-- Exclusions added in order to silence SLF4J warnings about multiple bindings:
http://www.slf4j.org/codes.html#multiple_bindings
-->
Expand Down
107 changes: 79 additions & 28 deletions src/main/java/com/conveyal/datatools/common/utils/aws/S3Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import static com.conveyal.datatools.common.utils.SparkUtils.logMessageAndHalt;
Expand All @@ -40,41 +41,21 @@ public class S3Utils {
public static final String DEFAULT_BUCKET;
public static final String DEFAULT_BUCKET_GTFS_FOLDER = "gtfs/";

public static final String APP_DATA_S3_REGION = "application.data.s3_region";

public static final String APP_DATA_CREDS_FILE = "application.data.s3_credentials_file";

static {
// Placeholder variables need to be used before setting the final variable to make sure initialization occurs
AmazonS3 tempS3Client = null;
AWSCredentialsProvider tempS3CredentialsProvider = null;
String tempGtfsS3Bucket = null;
S3ClientManagerImpl tempS3ClientManager = null;

// Only configure s3 if the config requires doing so
if (DataManager.useS3 || hasConfigProperty("modules.gtfsapi.use_extension")) {
try {
AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
String credentialsFile = DataManager.getConfigPropertyAsText("application.data.s3_credentials_file");
tempS3CredentialsProvider = credentialsFile != null ?
new ProfileCredentialsProvider(credentialsFile, "default") :
new DefaultAWSCredentialsProviderChain(); // default credentials providers, e.g. IAM role
builder.withCredentials(tempS3CredentialsProvider);

// If region configuration string is provided, use that.
// Otherwise defaults to value provided in ~/.aws/config
String region = DataManager.getConfigPropertyAsText("application.data.s3_region");
if (region != null) {
builder.withRegion(region);
}
tempS3Client = builder.build();
} catch (Exception e) {
LOG.error(
"S3 client not initialized correctly. Must provide config property application.data.s3_region or specify region in ~/.aws/config",
e
);
}

if (tempS3Client == null) {
throw new IllegalArgumentException("Fatal error initializing the default s3Client");
}
tempS3ClientManager = new S3ClientManagerImpl(tempS3Client);
S3Wrapper build = buildS3Wrapper(List.of(APP_DATA_CREDS_FILE), List.of(APP_DATA_S3_REGION));
tempS3CredentialsProvider = build.credentials;
tempS3ClientManager = new S3ClientManagerImpl(build.s3Client);

// s3 storage
tempGtfsS3Bucket = DataManager.getConfigPropertyAsText("application.data.gtfs_s3_bucket");
Expand All @@ -89,6 +70,76 @@ public class S3Utils {
DEFAULT_BUCKET = tempGtfsS3Bucket;
}

public static class S3Wrapper {
public final AWSCredentialsProvider credentials;
public final AmazonS3 s3Client;

public S3Wrapper(AWSCredentialsProvider credentials, AmazonS3 s3Client) {
this.credentials = credentials;
this.s3Client = s3Client;
}
}

/**
* Builds an S3 client from the specified credentials and region, or fallback to defaults
* using the ambient IAM role.
* @param configCredentials The credentials file to use for the client.
* @param configRegions The configuration entries in the order to try to get the AWS region to apply.
* @return An S3 client for the provided credentials and region.
*/
public static S3Wrapper buildS3Wrapper(
List<String> configCredentials,
List<String> configRegions
) throws IllegalArgumentException {
AmazonS3 s3client = null;
AWSCredentialsProvider credentialsProvider = null;
try {
AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
// Iterate through the credentials and stop at the first non-null returned.
// Default to the ambient IAM credentials, if any.
for (String configCred : configCredentials) {
String credentialsFile = DataManager.getConfigPropertyAsText(configCred);
if (credentialsFile != null) {
try {
credentialsProvider = new ProfileCredentialsProvider(credentialsFile, "default");
} catch (IllegalArgumentException e) {
LOG.error("Invalid credentials from {}. Trying the next one.", configCred, e);
}
if (credentialsProvider != null) break;
}
}
if (credentialsProvider == null) {
// default credentials providers, e.g. IAM role
credentialsProvider = new DefaultAWSCredentialsProviderChain();
}
builder.withCredentials(credentialsProvider);

// Iterate through the regions and stop at the first non-null returned.
// Otherwise defaults to value (typically provided in ~/.aws/config)
for (String configRegion : configRegions) {
String region = DataManager.getConfigPropertyAsText(configRegion);
if (region != null) {
builder.withRegion(region);
break;
}
}

s3client = builder.build();
} catch (Exception e) {
LOG.error(
"S3 client not initialized correctly. Must provide config property {} or specify region in ~/.aws/config",
configRegions,
e
);
}

if (s3client == null) {
throw new IllegalArgumentException("Fatal error initializing the default s3Client");
}

return new S3Wrapper(credentialsProvider, s3client);
}

/**
* Makes a key for an object id that is assumed to be in the default bucket's GTFS folder
*/
Expand All @@ -105,7 +156,7 @@ public static String getDefaultBucketUriForKey(String key) {
}

public static String getDefaultBucketUrlForKey(String key) {
return String.format("https://s3.amazonaws.com/%s/%s", DEFAULT_BUCKET, key);
return String.format("https://%s.s3.amazonaws.com/%s", DEFAULT_BUCKET, key);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ private String cascadeDeleteStop(Request req, Response res) {
int stopSequence = patternStop.getValue();
// Begin with the stop prior to the one deleted, unless at the beginning.
int beginWithSequence = (stopSequence != 0) ? stopSequence - 1 : stopSequence;
tableWriter.normalizeStopTimesForPattern(patternStop.getKey(), beginWithSequence, false);
tableWriter.normalizeStopTimesForPattern(patternStop.getKey(), beginWithSequence, false, false);
}
}
}
Expand Down Expand Up @@ -407,8 +407,9 @@ private String updateStopTimesFromPatternStops (Request req, Response res) {
try {
int beginStopSequence = Integer.parseInt(req.queryParams("stopSequence"));
boolean interpolateStopTimes = Boolean.parseBoolean(req.queryParams("interpolateStopTimes"));
boolean ignoreNonBlankStopTimes = Boolean.parseBoolean(req.queryParams("ignoreNonBlankStopTimes"));
JdbcTableWriter tableWriter = new JdbcTableWriter(table, datasource, namespace);
int stopTimesUpdated = tableWriter.normalizeStopTimesForPattern(patternId, beginStopSequence, interpolateStopTimes);
int stopTimesUpdated = tableWriter.normalizeStopTimesForPattern(patternId, beginStopSequence, interpolateStopTimes, ignoreNonBlankStopTimes);
return SparkUtils.formatJSON("updateResult", stopTimesUpdated + " stop times updated.");
} catch (Exception e) {
logMessageAndHalt(req, 400, "Error normalizing stop times", e);
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/conveyal/datatools/manager/DataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,25 +209,36 @@ static void registerRoutes() throws IOException {
SnapshotController.register(EDITOR_API_PREFIX);
EditorLockController.register(EDITOR_API_PREFIX);

new EditorControllerImpl(EDITOR_API_PREFIX, Table.AREAS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.AGENCY, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.ATTRIBUTIONS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.CALENDAR, DataManager.GTFS_DATA_SOURCE);
// NOTE: fare_attributes controller handles updates to nested table fare_rules.
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_ATTRIBUTES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_LEG_JOIN_RULES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_LEG_RULES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_MEDIAS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_PRODUCTS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_TRANSFER_RULES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.FEED_INFO, DataManager.GTFS_DATA_SOURCE);

// NOTE: Booking rules, locations and location shapes are GTFS Flex additions.
new EditorControllerImpl(EDITOR_API_PREFIX, Table.BOOKING_RULES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.LOCATIONS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.LOCATION_GROUP, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.LOCATION_GROUP_STOPS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.LOCATION_SHAPES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.NETWORKS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.RIDER_CATEGORIES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.ROUTES, DataManager.GTFS_DATA_SOURCE);
// NOTE: Patterns controller handles updates to nested tables shapes, pattern stops, and frequencies.
new EditorControllerImpl(EDITOR_API_PREFIX, Table.PATTERNS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.SCHEDULE_EXCEPTIONS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.STOPS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.TIME_FRAMES, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRANSLATIONS, DataManager.GTFS_DATA_SOURCE);
new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRIPS, DataManager.GTFS_DATA_SOURCE);

// TODO: Add transfers.txt controller?
}

Expand All @@ -248,7 +259,7 @@ static void registerRoutes() throws IOException {
String extensionFeedBucket = getExtensionPropertyAsText(extensionType, "s3_bucket");
String extensionBucketFolder = getExtensionPropertyAsText(extensionType, "s3_download_prefix");
int updateFrequency = getConfigProperty("modules.gtfsapi.update_frequency").asInt();
if (S3Utils.DEFAULT_BUCKET != null && extensionBucketFolder != null) {
if (extensionFeedBucket != null && extensionBucketFolder != null) {
FeedUpdater.schedule(updateFrequency, extensionFeedBucket, extensionBucketFolder);
}
else LOG.warn("FeedUpdater not initialized. S3 bucket and folder not provided.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.conveyal.datatools.manager.extensions.mtc;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.conveyal.datatools.common.utils.CloseableHttpURLConnection;
import com.conveyal.datatools.common.utils.aws.CheckedAWSException;
Expand Down Expand Up @@ -31,6 +32,8 @@
import java.util.List;
import java.util.Map;

import static com.conveyal.datatools.common.utils.aws.S3Utils.APP_DATA_CREDS_FILE;
import static com.conveyal.datatools.common.utils.aws.S3Utils.APP_DATA_S3_REGION;
import static com.conveyal.datatools.manager.models.ExternalFeedSourceProperty.constructId;
import static com.mongodb.client.model.Filters.eq;

Expand All @@ -54,6 +57,9 @@ public class MtcFeedResource implements ExternalFeedResource {
public static final String RESOURCE_TYPE = "MTC";
public static final String STOP_CODE_PRIMARY_PREFIX_FIELD_NAME = "PrimaryPrefix";
public static final String STOP_CODE_SECONDARY_PREFIXES_FIELD_NAME = "SecondaryPrefixes";
public static final String CONFIG_MTC_CREDENTIALS = "extensions.mtc.s3_credentials_file";
public static final String CONFIG_MTC_REGION = "extensions.mtc.s3_region";
private static S3Utils.S3Wrapper s3Wrapper;

private String rtdApi, s3Bucket, s3Prefix;

Expand Down Expand Up @@ -212,7 +218,7 @@ public void feedVersionCreated(
LOG.info("Pushing to MTC S3 Bucket: s3://{}/{}", s3Bucket, keyName);
File file = feedVersion.retrieveGtfsFile();
try {
S3Utils.getDefaultS3Client().putObject(new PutObjectRequest(s3Bucket, keyName, file));
getS3Client().putObject(new PutObjectRequest(s3Bucket, keyName, file));
} catch (Exception e) {
LOG.error("Could not upload feed version to s3.");
e.printStackTrace();
Expand Down Expand Up @@ -354,4 +360,26 @@ public static List<String> getSecondaryStopCodePrefixes(Map<String, Map<String,
String secondaryStopPrefixValue = MtcFeedResource.getFieldValue(properties, MtcFeedResource.STOP_CODE_SECONDARY_PREFIXES_FIELD_NAME);
return (secondaryStopPrefixValue == null) ? null : List.of(secondaryStopPrefixValue.split(","));
}

/**
* Builds the S3 wrapper to access the MTC feed processing bucket,
* which needs separate credentials from the rest of datatools.
*/
static S3Utils.S3Wrapper getS3Wrapper() {
List<String> configRegions = List.of(CONFIG_MTC_REGION, APP_DATA_S3_REGION);
List<String> configCredentials = List.of(CONFIG_MTC_CREDENTIALS, APP_DATA_CREDS_FILE);
return S3Utils.buildS3Wrapper(configCredentials, configRegions);
}

/**
* Get the S3 client from a cached wrapper to access the MTC feed processing bucket.
* Note: In S3Utils, an AWSClientManager is used, however in practice, only the default client is invoked
* (i.e. with role=null, region=null), so the logical path returns the original s3Client, which we are doing here.
*/
public static AmazonS3 getS3Client() {
if (s3Wrapper == null) {
s3Wrapper = getS3Wrapper();
}
return s3Wrapper.s3Client;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.conveyal.datatools.common.utils.aws.CheckedAWSException;
import com.conveyal.datatools.common.utils.aws.S3Utils;
import com.conveyal.datatools.manager.extensions.mtc.MtcFeedResource;
import com.conveyal.datatools.manager.models.ExternalFeedSourceProperty;
import com.conveyal.datatools.manager.models.FeedSource;
import com.conveyal.datatools.manager.models.FeedVersion;
Expand Down Expand Up @@ -406,7 +406,7 @@ private FeedVersion findMatchingFeedVersion(
) throws AmazonServiceException, IOException, CheckedAWSException {
String filename = keyName.split("/")[1];
String feedId = filename.replace(".zip", "");
S3Object object = S3Utils.getDefaultS3Client().getObject(feedBucket, keyName);
S3Object object = MtcFeedResource.getS3Client().getObject(feedBucket, keyName);
File file = new File(FeedStore.basePath, filename);
try (
InputStream in = object.getObjectContent();
Expand Down Expand Up @@ -447,17 +447,14 @@ public interface CompletedFeedRetriever {

/**
* Implements the default behavior for above interface.
* This method uses extensions.mtc.s3_credentials_file and s3_region, if populated,
* and falls back to the application's S3 credentials and region otherwise.
*/
public class DefaultCompletedFeedRetriever implements CompletedFeedRetriever {
@Override
public List<S3ObjectSummary> retrieveCompletedFeeds() {
try {
ObjectListing gtfsList = S3Utils.getDefaultS3Client().listObjects(feedBucket, bucketFolder);
return gtfsList.getObjectSummaries();
} catch (CheckedAWSException e) {
LOG.error("Failed to list S3 Objects", e);
return null;
}
ObjectListing gtfsList = MtcFeedResource.getS3Client().listObjects(feedBucket, bucketFolder);
return gtfsList.getObjectSummaries();
}
}
}
Loading
Loading