-
Notifications
You must be signed in to change notification settings - Fork 18
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
Fix false positives in fastly
and fastly-compute
deployment types
#1148
Conversation
fastly
and fastly-compute
deployment types
fastly
and fastly-compute
deployment typesfastly
and fastly-compute
deployment types
) | ||
FastlyApiClientProvider.get(keyRing) match { | ||
case None => | ||
resources.reporter.fail("Failed to fetch Fastly API credentials") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth expanding this slightly to give a clearer sense of where credentials should exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Small code style advice (non-blocking though): I'd probably favour pulling the case Some(client) => ...
body out into a function to improve readability - as easier to see the actual patterns being matched. And have the function return a Try[..]
rather than a large try/catch - again as it makes it easier to scan quickly the actual flow. But this is somewhat subjective.
This was closed by mistake - reopened it and refactored it with Nic's suggestion |
This PR is stale because it has been open 30 days with no activity. Unless a comment is added or the “stale” label removed, this will be closed in 3 days |
🥹 |
… retrieve API credentials
e158b20
to
fe5d76d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made a few suggestions, but this already looks like a good change that would be great to get merged.
): Unit = { | ||
FastlyApiClientProvider.get(keyRing) match { | ||
case None => | ||
resources.reporter.fail("Failed to fetch Fastly API credentials") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resources.reporter.fail("Failed to fetch Fastly API credentials") | |
resources.reporter.fail("Failed to fetch Fastly API credentials from keyring") |
FastlyApiClientProvider.get(keyRing) match { | ||
case None => | ||
resources.reporter.fail("Failed to fetch Fastly API credentials") | ||
case Some(client) => | ||
_execute(client, resources, stopFlag) match { | ||
case Success(nextVersionNumber) => | ||
resources.reporter | ||
.info(s"Fastly version $nextVersionNumber is now active") | ||
case Failure(err) => | ||
resources.reporter.fail( | ||
s"$err. Your API key may be invalid or it may have expired" | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be slightly easier to read:
FastlyApiClientProvider.get(keyRing) match { | |
case None => | |
resources.reporter.fail("Failed to fetch Fastly API credentials") | |
case Some(client) => | |
_execute(client, resources, stopFlag) match { | |
case Success(nextVersionNumber) => | |
resources.reporter | |
.info(s"Fastly version $nextVersionNumber is now active") | |
case Failure(err) => | |
resources.reporter.fail( | |
s"$err. Your API key may be invalid or it may have expired" | |
) | |
} | |
override def execute( | |
resources: DeploymentResources, | |
stopFlag: => Boolean | |
): Unit = { | |
FastlyApiClientProvider | |
.get(keyRing) | |
.map(_execute(_, resources, stopFlag)) match { | |
case Some(Success(nextVersionNumber)) => | |
resources.reporter | |
.info(s"Fastly version $nextVersionNumber is now active") | |
case Some(Failure(err)) => | |
resources.reporter.fail( | |
s"$err. Your API key may be invalid or it may have expired" | |
) | |
case None => | |
resources.reporter.fail("Failed to fetch Fastly API credentials") | |
} | |
} |
@@ -30,43 +31,73 @@ case class UpdateFastlyConfig(s3Package: S3Path)(implicit | |||
implicit val ec: ExecutionContextExecutorService = | |||
ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(10)) | |||
|
|||
override def execute( | |||
private def _execute( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more meaningful name for this method? Perhaps executeWithCredentials
?
.info( | ||
s"Fastly Compute@Edge service ${client.serviceId} - version $nextVersionNumber is now active" | ||
FastlyApiClientProvider.get(keyRing) match { | ||
case None => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar flattening of pattern match could be done as for FastlyTask.scala
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - yes, I'm not a big fan of nested pattern matching either. Have refactored accordingly :)
Flatten pattern matching to improve readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Might be nice to have a 👍 from a current member of devX?
) | ||
case Some((_, Failure(err))) => | ||
resources.reporter.fail( | ||
s"$err. Your API key may be invalid or it may have expired" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor:
IIUC, this case is going to catch a number of potential errors (network problems, Fastly API downtime/errors) as well as the problems that we've already mentioned in the error message.
If we find reliability problems with this deployment type in the future, it might be worth extracting the specific error (perhaps by adding some verbose logging or a different return type to activateVersion
), but I don't think that needs to block this PR (which is already a big improvement!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this some more, I think there is another potential false positive here. IIUC calling activateVersion
can result in a successful Future
(i.e. we got a Response
from the Fastly API), where the response/status code indicates that the request was unsuccessful from Fastly's perspective (i.e. we got a 500 back and did not actually activate the new version). In this case we will still match on: case Some((client, Success(nextVersionNumber)))
.
Happy to pair on fixing that via a separate PR if helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work; thanks for improving this and documenting the testing so clearly 👍
What does this change?
Fixes an issue with
fastly
andfastly-compute
deployment types that incorrectly deploy successfully when no API token is present in the keyring.This is a problem because you might deploy your VCL or Compute@Edge application and think everything has gone smoothly, when in reality nothing has happened because the
execute
function wasn't triggered.In its current implementation,
foreach
is called on the optionalFastlyApiClientProvider.get(keyring)
function, meaning thatexecute
will only run if it is aSome
value. No implementation is defined when it'sNone
.How to test
Deployed to CODE Riff-Raff.
Scenario 1: Fastly API key not present in the parameter store (should fail)
Scenario 2: Invalid or expired Fastly API key present in the parameter store (should fail)
Scenario 3: Valid Fastly API key present in the parameter store (should succeed)