aws / copilot-cli

The AWS Copilot CLI is a tool for developers to build, release and operate production ready containerized applications on AWS App Runner or Amazon ECS on AWS Fargate.
https://aws.github.io/copilot-cli/
Apache License 2.0
3.54k stars 418 forks source link

misleading suggested `copilot env init` command #3685

Open AnthonyFoiani-at opened 2 years ago

AnthonyFoiani-at commented 2 years ago

Hello!

I'm using copilot for the first time, and I walked into a bit of a wall.

The output from my copilot init included this suggestion:

No problem, you can deploy your service later:

  • Run copilot env init --name test --profile default --app ajf-demo to create your staging environment.

The problem is that I ran copilot init with a specific profile set in my AWS_PROFILE environment variable, and it wasn't default. 😬

When I first read the suggestion, I though that default referred to some default within copilot or elsewhere within ECS. I didn't stop to think that it's the plain old --profile argument!

Anyway, it might be worth changing that suggested output to use the current AWS_PROFILE value, or omit it entirely if the original command also omitted it?

(It would also have been a bit more obvious if it came right after copilot, to indicate it's an arg to copilot itself, and not to any sub-command -- but I don't know if your arg parser can handle that?)

Thanks!

p.s. The error was a bit odd, too:

✘ get identity: get caller identity: NoCredentialProviders: no valid providers in chain
caused by: EnvAccessKeyNotFound: failed to find credentials in the environment.
SharedCredsLoad: failed to load profile, default.
EC2RoleRequestError: no EC2 instance role found
caused by: RequestError: send request failed
caused by: Get "http://169.254.169.254/latest/meta-data/iam/security-credentials/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

As I spent some quality time with IMDSv1 / IMDSv2 issues earlier this year, I followed that wrong path for a bit...

iamhopaul123 commented 2 years ago

Hello @AnthonyFoiani-at. Overall I think your suggestion totally makes sense to me.

The problem is that I ran copilot init with a specific profile set in my AWS_PROFILE environment variable, and it wasn't default. 😬

Agreed. I think we should consider users might not have a profile named default.

p.s. The error was a bit odd, too:

I am a little confused about this one since I've never seen that before. Could you provide a little more context on what commands did you run to get into this? Thank you!

AnthonyFoiani-at commented 2 years ago

Hello @AnthonyFoiani-at. Overall I think your suggestion totally makes sense to me.

The problem is that I ran copilot init with a specific profile set in my AWS_PROFILE environment variable, and it wasn't default. 😬

Agreed. I think we should consider users might not have a profile named default.

More specifically, if a user is running with a specific AWS_PROFILE value set, it seems likely that they'd want that same value in any suggested command.

p.s. The error was a bit odd, too:

I am a little confused about this one since I've never seen that before. Could you provide a little more context on what commands did you run to get into this? Thank you!

I ran this command:

copilot env init --name test --profile default --app ajf-demo

And got this output:

Default environment configuration? Yes, use default.
✘ get identity: get caller identity: NoCredentialProviders: no valid providers in chain
caused by: EnvAccessKeyNotFound: failed to find credentials in the environment.
SharedCredsLoad: failed to load profile, default.
EC2RoleRequestError: no EC2 instance role found
caused by: RequestError: send request failed
caused by: Get "http://169.254.169.254/latest/meta-data/iam/security-credentials/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

And because I don't have a default profile (or, if I do, it doesn't have any creds), the "find credentials any possible way" eventually falls back to "assume we're running on EC2 [or some other platform with a compatible IMDSv1 service] and try to pull credentials from IMDS."

So ultimately it exhausted every method it knew to try to find credentials.

Unfortunately, the last step has a very long timeout (90+ seconds -- that should probably reduced to something more like 10 or even 5 seconds, IMHO).

Also, the IMDS URL in the error made me think it might have been an IMDSv1 vs. IMDSv2 issue (which, if I'd stopped and thought about it, would likely have been a 403 or 404, not a hang.)

(And I just checked; the Go SDK absolutely does IMDSv2 and [AFAICT] by default: aws/ec2metadata/token_provider.go ).

So mostly pilot error, just a pilot that is easily confused. :-)

dannyrandall commented 2 years ago

Thanks for the information! Although this doesn't address the env init enhancement, we currently have a PR open to make the error more clear and reduce the time before it fails to 10 seconds - https://github.com/aws/copilot-cli/pull/3645. The error message we'll show is here; feel free to take a look and leave a comment over there if you think a different message would have helped you troubleshoot better.😊