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

Add --stage argument to chalice commands #270

Closed
wants to merge 14 commits into from

Conversation

jamesls
Copy link
Member

@jamesls jamesls commented Mar 30, 2017

This pr builds on #264
to provide a consistent CLI experience when working with chalice stages.

There's several changes in this PR.

First, the code now clearly indicates whether we mean "chalice stage", which is
a completely separate collection of AWS resources, or an "API Gateway stage"
which is a specific configuration within a chalice stage (it's essentially the
URL prefix to use for your REST API for now). chalice_stage_name is
generally used when we mean a chalice stage and api_gateway_stage is used
when we mean the latter, and with the exception of the actual CLI option
(--stage) every existing reference to a "stage" has been renamed to one
of those two values.

Next, I've deprecated the form "chalice deploy ". You now get an error
message if you use this form which instructs you use to use
--api-gateway-stage:

$ chalice deploy prod
You've specified a deploy command of the form 'chalice deploy <stage>'
This form is deprecated and will be removed in a future version of chalice.
You can use the --api-gateway-stage to achieve the same functionality, or the newer '--stage' argument if you want an entirely set of separate resources.

To get the new stage functionality introduced in #264 you need to use
chalice deploy --stage prod.

And finally, I've added a --stage option to the remaining set of chalice
commands that should be stage specific:

  • url
  • logs
  • generate-sdk
  • package

All of these commands have also been updated to pull the deployed values
from the .chalice/deployed.json file instead of trying to query it using
the SDK as it was doing previously.

jamesls added 5 commits March 29, 2017 14:37
This is used to track when major features are introduced
in the config file.  Version is missing in existing config files
so it will be assumed to be 1.0, hence the starting value of
"2.0" in this commit.
This refactoring makes it easier to write CLI tests
for all the various commands.
Remove all references to a plain "stage_name".  Stage names
are now explicit.  Either you mean "API Gateway stage name"
or "chalice stage name".
This allows for some configuratio to be specified
as a top level key in .chalice/config.json as well as
a chalice stage specific value.  Now that chalice stages
are completely separate sets of resources, you can have
different config values per stage.
The "chalice deploy <stage>" is deprecated.  Instead, I've
added two options in its place:

* --api-gateway-stage, for users that want the existing behavior
* --stage, for the new stage behavior which creates an entirely separate
  set of AWS resources.

I've also added a deprecation warning if you specify a positional stage
as well as param validation if you specify both the api gateway stage
as well as the positional stage param.

As part of this commit I've also updated the remaining commands that
need to be stage aware:

* package
* url
* generate-sdk
* logs

For each of these commands I've added a "--stage" option that uses the
deployed values JSON file to look up the appropriate stage values.
exception = Exception(
"Unable to import your app.py file: %s" % e
)
# exception.exit_code = 2
Copy link
Contributor

Choose a reason for hiding this comment

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

Whats this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Old code I need to update. This code was originally from the cli init.py which used click exceptions to propagate exit codes.

]
def _chain_lookup(self, name, varies_per_chalice_stage=False):
# type: (str, bool) -> Any
all_dicts = [self._user_provided_params]
Copy link
Contributor

Choose a reason for hiding this comment

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

all_dicts is probably not the best name considering that another dict is added to it if varies_per_chalice_stage is true. How bout something like search_dicts?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

@codecov-io
Copy link

codecov-io commented Mar 30, 2017

Codecov Report

Merging #270 into package will increase coverage by 1.77%.
The diff coverage is 92.19%.

Impacted file tree graph

@@             Coverage Diff             @@
##           package     #270      +/-   ##
===========================================
+ Coverage    83.98%   85.75%   +1.77%     
===========================================
  Files           17       17              
  Lines         1592     1664      +72     
  Branches       196      201       +5     
===========================================
+ Hits          1337     1427      +90     
+ Misses         202      184      -18     
  Partials        53       53
Impacted Files Coverage Δ
chalice/package.py 97.1% <100%> (ø) ⬆️
chalice/awsclient.py 82.14% <100%> (+0.12%) ⬆️
chalice/constants.py 100% <100%> (ø)
chalice/deploy/deployer.py 73.43% <100%> (ø) ⬆️
chalice/cli/factory.py 88.76% <88.76%> (ø)
chalice/config.py 97.29% <96.15%> (+6.38%) ⬆️
chalice/__init__.py 75.14% <0%> (-24.86%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7607b22...82e4005. Read the comment docs.

deprecated_api_gateway_stage is not None:
raise _create_deprecated_stage_error(api_gateway_stage,
deprecated_api_gateway_stage)
if api_gateway_stage is None and deprecated_api_gateway_stage is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this just be deprecated_api_gateway_stage is not None?

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated, that was before adding the mutually exclusive part validation so the first clause isn't needed anymore.

"Are you sure this is a chalice project?")
app_obj = self.load_chalice_app()
user_provided_params['chalice_app'] = app_obj
if autogen_policy is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why would autogen_policy be None?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm double checking on this, but I think this code is no longer relevant.

The idea a while back was to toggle between three states: not set, true, and false. This specific check was to check if the user explicitly set a true/false value and if so then add it to the dict of user provided params. The "not set" was needed because of config precedence. If this option was not set, then move on to the next dict in the _chain_lookup of the Config obj.

Copy link
Member Author

Choose a reason for hiding this comment

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

It looks like you could never set autogen_policy from the config file, only via the CLI.

I think the policy management and configuration could use a refresh. This would be a fairly large change (I think) so I'll address this in a separate PR.

Copy link
Contributor

@kyleknap kyleknap left a comment

Choose a reason for hiding this comment

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

Looks good. Just mainly small questions and comments


def _warn_pending_removal(deprecated_stage):
# type: (str) -> None
click.echo("You've specified a deploy command of the form "
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be to stderr?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed. I updated all the error messages to print to stderr.

@@ -201,11 +218,17 @@ def deploy(ctx, autogen_policy, profile, stage):
@click.option('--include-lambda-messages/--no-include-lambda-messages',
default=False,
help='Controls whether or not lambda log messages are included.')
@click.option('--stage', default='dev')
Copy link
Contributor

Choose a reason for hiding this comment

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

Are users able to set the default for stage to override dev as the default? If so how does that happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, not right now. I'm hesitant to allow people to change the default to something like "prod". I'd prefer if you're deploying from a script you have to run --stage prod.

Copy link
Contributor

Choose a reason for hiding this comment

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

That makes sense to be explicit, especially for debugging purposes.

"region value in our ~/.aws/config file.")
return 2
except Exception as e:
click.echo(str(e))
Copy link
Contributor

Choose a reason for hiding this comment

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

Might want to print this to stderr as well.

the config.environment_variables would be::

{"TABLE": "foo", "S3BUCKET": "devbucket"}

Copy link
Contributor

Choose a reason for hiding this comment

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

And so prod would be?
{"TABLE": "prodtable", "S3BUCKET": "prodbucket"}

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah. I updated the docs.

]
def _chain_lookup(self, name, varies_per_chalice_stage=False):
# type: (str, bool) -> Any
all_dicts = [self._user_provided_params]
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah or cfg_dicts_chain?

def __init__(self,
chalice_stage='dev',
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a lot of hardcoded default dev values. Wonder if it makes sense to have it be a constant to import or required instead of optional in case it ever needs to be updated?

Copy link
Member Author

Choose a reason for hiding this comment

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

I created a constants.py and moved a few of the constants over to that module.

assert logging.getLogger('').level == logging.DEBUG


def test_can_create_botocoreo_session_cli_factory(clifactory):
Copy link
Contributor

Choose a reason for hiding this comment

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

typo botocoreo --> botocore

# This is the version that's written to the config file
# on a `chalice new-project`. It's also how chalice is able
# to know when to warn you when changing behavior is introduced.
CONFIG_VERSION = '2.0'
Copy link
Contributor

Choose a reason for hiding this comment

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

We should maybe throw errors if we encounter a config version higher than that version of the chalice can support

Copy link
Member Author

Choose a reason for hiding this comment

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

Seems reasonable, I'll update.

@jamesls
Copy link
Member Author

jamesls commented Mar 31, 2017

@kyleknap I believe all the feedback's been incorporated.

Copy link
Contributor

@kyleknap kyleknap left a comment

Choose a reason for hiding this comment

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

Looks good. I like the addition of the constants module.

Before it would just print the top level file where the
error occurs.  Now it tries to reconstruct the error message
you'd see if you let a syntaxerror propagate.  This should help
in troubleshooting.
@jamesls
Copy link
Member Author

jamesls commented Mar 31, 2017

Cool, also @stealthycoin I improved the error messages on import errors:

 $ chalice deploy
Unable to import your app.py file:

File "/private/tmp/error/errors/chalicelib/james.py", line 1
  this is a syntax error in chalicelib/james.py

SyntaxError: invalid syntax

@jamesls
Copy link
Member Author

jamesls commented Mar 31, 2017

Rebased and merged in 76bd8e1

@jamesls jamesls closed this Mar 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants