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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 馃徆 Implement Shuttle Route KML Save to S3 #984

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

nlwstein
Copy link
Contributor

@nlwstein nlwstein commented Jun 11, 2024

Summary of changes

Asana Ticket: 馃徆 Implement Shuttle Route KML Save to S3

  • Uploaded shape files are now stored in S3.
  • Uploaded shape files can be downloaded securely from their record in the dashboard.
  • Uploaded shape files are deleted from S3 upon deletion of the record.
  • Uploaded shape files cannot squash existing files. This deviates slightly from the ticket description - I feel that it is simpler to just tell the user that the file already exists, since I would imagine these are only being managed from this UI going forward. If we need the ability to squash as opposed to the user simply renaming the file, I think we should automatically detect the existing record and prompt them to remove that as well to keep a 1:1 relationship between file in s3 and record in arrow.

Reviewer Checklist

  • Meets ticket's acceptance criteria
  • Any new or changed functions have typespecs
  • Tests were added for any new functionality (don't just rely on Codecov)
  • This branch was deployed to the staging environment and is currently running with no unexpected increase in warnings, and no errors or crashes.

@nlwstein nlwstein changed the base branch from master to meag/add-phx7-core-components June 11, 2024 19:11
@nlwstein nlwstein changed the base branch from meag/add-phx7-core-components to meag/add-shuttle-shape-page June 11, 2024 19:11
Copy link

Coverage of commit 332d995

Summary coverage rate:
  lines......: 79.1% (782 of 989 lines)
  functions..: 61.6% (568 of 922 functions)
  branches...: no data found

Files changed coverage rate:
                                                                     |Lines       |Functions  |Branches    
  Filename                                                           |Rate     Num|Rate    Num|Rate     Num
  =========================================================================================================
  lib/arrow/shuttle.ex                                               |58.3%     36|84.6%    13|    -      0
  lib/arrow/shuttle/shape.ex                                         | 100%      2|83.3%     6|    -      0
  lib/arrow_web/controllers/shape_controller.ex                      |76.7%     30|85.7%    14|    -      0
  lib/arrow_web/router.ex                                            |90.5%     21|40.7%    81|    -      0
  test/support/fixtures/shuttle_fixtures.ex                          | 100%      4| 100%     3|    -      0

Download coverage report

Copy link

Coverage of commit ad0f4d7

Summary coverage rate:
  lines......: 79.1% (785 of 992 lines)
  functions..: 61.6% (568 of 922 functions)
  branches...: no data found

Files changed coverage rate:
                                                                     |Lines       |Functions  |Branches    
  Filename                                                           |Rate     Num|Rate    Num|Rate     Num
  =========================================================================================================
  lib/arrow/shuttle.ex                                               |61.5%     39|84.6%    13|    -      0
  lib/arrow/shuttle/shape.ex                                         | 100%      2|83.3%     6|    -      0
  lib/arrow_web/controllers/shape_controller.ex                      |76.7%     30|85.7%    14|    -      0
  lib/arrow_web/router.ex                                            |90.5%     21|40.7%    81|    -      0
  test/support/fixtures/shuttle_fixtures.ex                          | 100%      4| 100%     3|    -      0

Download coverage report

Copy link

Coverage of commit ad0f4d7

Summary coverage rate:
  lines......: 79.1% (785 of 992 lines)
  functions..: 61.6% (568 of 922 functions)
  branches...: no data found

Files changed coverage rate:
                                                                     |Lines       |Functions  |Branches    
  Filename                                                           |Rate     Num|Rate    Num|Rate     Num
  =========================================================================================================
  lib/arrow/shuttle.ex                                               |61.5%     39|84.6%    13|    -      0
  lib/arrow/shuttle/shape.ex                                         | 100%      2|83.3%     6|    -      0
  lib/arrow_web/controllers/shape_controller.ex                      |76.7%     30|85.7%    14|    -      0
  lib/arrow_web/router.ex                                            |90.5%     21|40.7%    81|    -      0
  test/support/fixtures/shuttle_fixtures.ex                          | 100%      4| 100%     3|    -      0

Download coverage report

Copy link

Coverage of commit ad0f4d7

Summary coverage rate:
  lines......: 79.1% (785 of 992 lines)
  functions..: 61.6% (568 of 922 functions)
  branches...: no data found

Files changed coverage rate:
                                                                     |Lines       |Functions  |Branches    
  Filename                                                           |Rate     Num|Rate    Num|Rate     Num
  =========================================================================================================
  lib/arrow/shuttle.ex                                               |61.5%     39|84.6%    13|    -      0
  lib/arrow/shuttle/shape.ex                                         | 100%      2|83.3%     6|    -      0
  lib/arrow_web/controllers/shape_controller.ex                      |76.7%     30|85.7%    14|    -      0
  lib/arrow_web/router.ex                                            |90.5%     21|40.7%    81|    -      0
  test/support/fixtures/shuttle_fixtures.ex                          | 100%      4| 100%     3|    -      0

Download coverage report

http_client: HTTPoison,
shape_storage_enabled?: false,
shape_storage_prefix_env: "arrow-dev-local",
shape_storage_bucket: "mbta-gtfs-s3-sandbox",
Copy link
Contributor Author

@nlwstein nlwstein Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be mbta-arrow, but I do not have write access at least with my credentials.

@@ -34,7 +34,11 @@ config :arrow,
},
time_zone: "America/New_York",
ex_aws_requester: {Fake.ExAws, :admin_group_request},
http_client: HTTPoison
http_client: HTTPoison,
shape_storage_enabled?: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabled by default, and just stores disabled as the value for all of the relevant s3 columns.

http_client: HTTPoison
http_client: HTTPoison,
shape_storage_enabled?: false,
shape_storage_prefix_env: "arrow-dev-local",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The storage path is like this: $PREFIX/$PREFIX_ENV/the_file.kml. In prod, the prefix_env is set via the existing AWS env var.

@@ -2,6 +2,10 @@
<aside role="alert" class="alert alert-info"><%= message %></aside>
<% end %>

<%= with message when is_binary(message) <- Phoenix.Flash.get(@flash, :error) do %>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to display a simple error flash - it looks like the existing error flash was designed to show a whole collection of errors (form validation).

|> Plug.Conn.resp(:found, "")
|> Plug.Conn.put_resp_header(
"location",
"https://#{shape.bucket}.s3.amazonaws.com/#{shape.path}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why I store the bucket and path - it may be a pre-optimization but should help if we ever have to rename these things vs. string replacing a URL column.

@@ -51,6 +51,8 @@ defmodule Arrow.MixProject do
{:ex_aws_rds, "~> 2.0"},
{:ex_aws_secretsmanager, "~> 2.0"},
{:ex_aws, "~> 2.1"},
{:ex_aws_s3, "~> 2.1"},
{:sweet_xml, "~> 0.7.4"},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet_xml is soft-required by ex_aws_s3.

@@ -20,11 +20,24 @@ defmodule Arrow.ShuttleTest do
assert Shuttle.get_shape!(shape.id) == shape
end

test "create_shape/1 with valid data creates a shape" do
valid_attrs = %{name: "some name"}
test "create_shape/1 with valid data creates a shape and uploads to s3" do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated our "good-path" test to also actually upload to S3.

My one concern with this is storage usage over time without a cleanup routine. I think the cleanest implementation would be to update the policy to whack anything with arrow/test-runner/* older than n days, vs cleaning it up in the test, because runs that fail may leave detritus on the bucket.

@nlwstein nlwstein changed the title Nlws s3 upload feat: 馃徆 Implement Shuttle Route KML Save to S3 Jun 12, 2024
@nlwstein nlwstein requested a review from meagharty June 12, 2024 13:43
@nlwstein
Copy link
Contributor Author

@meagharty There are a few outstanding issues here that aren't really related to the core feature but may block it's acceptance into the repo until they are complete:

  1. S3 bucket mbta-arrow's permissions don't seem to be right. (Also, my tester S3 bucket mbta-gtfs-s3-sandbox's permissions are fine for writing but it does not have public read and thus the /shape/{id}/download route isn't working quite right, but we shouldn't fix this...and just update the correct bucket!)
  2. The tests fail on GitHub because the AWS user has less permissions than I do to interact with S3.
  3. We should also add a policy for truncating the test files uploaded (and possibly the dev env files uploaded) to avoid a ton of useless storage accumulation on s3.

Otherwise, I think the feature as-is can be reviewed while we deal with these issues 馃槃 If you disagree I can take it back as a draft while I resolve these things.

@nlwstein nlwstein marked this pull request as ready for review June 12, 2024 13:47
"path" => "some/path/to/sample.kml",
"prefix" => prefix,
"bucket" => Application.get_env(:arrow, :shape_storage_bucket),
"filename" => %Plug.Upload{filename: "sample.kml", path: "test_files/sample.kml"}
Copy link
Collaborator

@meagharty meagharty Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking: we could resolve this in a future PR since the full featureset is expected to extract individual shapes from a KML file (not part of this PR)

But: I was talking with @bfauble and we might want this filename to be saved as #{name}.kml. To make the names easier to reconcile between gtfs_creator and arrow.

I am pro-keeping the KML format around since it's industry common.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meagharty This is a great idea and would also mean that we could drop the columns eventually - since the file path / name / etc. would be inherent.

I guess an alternative would be a "smart" connection between the two systems where it would pull some metadata JSON payload, which might be more extensible long term BUT I think starting with the names makes a lot of sense.

It would be an easy change here, too!

Copy link
Contributor Author

@nlwstein nlwstein Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also feel like this could be a follow up ticket, just to avoid this getting stuck in review as long as you're cool with that (re: non-blocking).

@meagharty meagharty mentioned this pull request Jun 13, 2024
4 tasks
Base automatically changed from meag/add-shuttle-shape-page to master June 13, 2024 15:59
@meagharty meagharty self-requested a review June 14, 2024 18:56
Copy link

Coverage of commit 49bf9d2

Summary coverage rate:
  lines......: 80.4% (813 of 1011 lines)
  functions..: 61.7% (586 of 950 functions)
  branches...: no data found

Files changed coverage rate:
                                                                     |Lines       |Functions  |Branches    
  Filename                                                           |Rate     Num|Rate    Num|Rate     Num
  =========================================================================================================
  lib/arrow/mock/exaws/request.ex                                    | 100%      1| 100%     1|    -      0
  lib/arrow/shuttle.ex                                               |86.0%     43|92.3%    13|    -      0
  lib/arrow/shuttle/shape.ex                                         | 100%      2|83.3%     6|    -      0
  lib/arrow_web/controllers/shape_controller.ex                      |85.3%     34|92.9%    14|    -      0
  lib/arrow_web/router.ex                                            |95.2%     21|41.4%    87|    -      0
  test/support/fixtures/shuttle_fixtures.ex                          | 100%      4| 100%     3|    -      0

Download coverage report

@nlwstein nlwstein requested review from a team and bfauble and removed request for a team June 21, 2024 15:46

config :arrow,
shape_storage_enabled?: true,
shape_storage_prefix_env: System.get_env("AWS_SECRET_PREFIX") || "arrow-prod-unknown"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of having this default, should it just be nil and included as part of the check with enabled?

case upload_shape(attrs["filename"]) do
{:ok, new_attrs} ->
# Delete old file:
{:ok, _} = delete_shape_file(shape)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there not a way to just overwrite when uploading?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants