diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5786bcdb7..415e4c596 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,8 @@ Next Release (TBD) (`#163 `__) * Map cognito user pool claims as part of request context (`#165 `__) +* Add ``chalice url`` command to print the deployed URL + (`#169 `__) 0.4.0 diff --git a/chalice/cli/__init__.py b/chalice/cli/__init__.py index 7d391e59c..8a8e84cd1 100644 --- a/chalice/cli/__init__.py +++ b/chalice/cli/__init__.py @@ -110,6 +110,28 @@ def inject_large_request_body_filter(): log.addFilter(LargeRequestBodyFilter()) +def create_config_obj(ctx, stage_name=None, autogen_policy=None, profile=None): + user_provided_params = {} + project_dir = ctx.obj['project_dir'] + default_params = {'project_dir': project_dir} + try: + config_from_disk = load_project_config(project_dir) + except (OSError, IOError): + click.echo("Unable to load the project config file. " + "Are you sure this is a chalice project?") + raise click.Abort() + app_obj = load_chalice_app(project_dir) + user_provided_params['chalice_app'] = app_obj + if stage_name is not None: + user_provided_params['stage'] = stage_name + if autogen_policy is not None: + user_provided_params['autogen_policy'] = autogen_policy + if profile is not None: + user_provided_params['profile'] = profile + config = Config(user_provided_params, config_from_disk, default_params) + return config + + class LargeRequestBodyFilter(logging.Filter): def filter(self, record): if record.msg.startswith('Making request'): @@ -126,60 +148,40 @@ def filter(self, record): @click.group() @click.version_option(version=chalice_version, message='%(prog)s %(version)s') -@click.pass_context -def cli(ctx): - pass - - -@cli.command() @click.option('--project-dir', help='The project directory. Defaults to CWD') +@click.option('--debug/--no-debug', + default=False, + help='Print debug logs to stderr.') @click.pass_context -def local(ctx, project_dir): +def cli(ctx, project_dir, debug=False): if project_dir is None: project_dir = os.getcwd() + ctx.obj['project_dir'] = project_dir + ctx.obj['debug'] = debug os.chdir(project_dir) - app_obj = load_chalice_app(project_dir) + + +@cli.command() +@click.pass_context +def local(ctx): + app_obj = load_chalice_app(ctx.obj['project_dir']) run_local_server(app_obj) @cli.command() -@click.option('--project-dir', - help='The project directory. Defaults to CWD') @click.option('--autogen-policy/--no-autogen-policy', default=True, help='Automatically generate IAM policy for app code.') @click.option('--profile', help='Override profile at deploy time.') -@click.option('--debug/--no-debug', - default=False, - help='Print debug logs to stderr.') @click.argument('stage', nargs=1, required=False) @click.pass_context -def deploy(ctx, project_dir, autogen_policy, profile, debug, stage): - user_provided_params = {} - default_params = {} - if project_dir is None: - project_dir = os.getcwd() - default_params['project_dir'] = project_dir - else: - user_provided_params['project_dir'] = project_dir - os.chdir(project_dir) - try: - config_from_disk = load_project_config(project_dir) - except (OSError, IOError): - click.echo("Unable to load the project config file. " - "Are you sure this is a chalice project?") - raise click.Abort() - if stage is not None: - config_from_disk['stage'] = stage - default_params['stage'] = stage - app_obj = load_chalice_app(project_dir) - user_provided_params['chalice_app'] = app_obj - user_provided_params['autogen_policy'] = autogen_policy - if profile: - user_provided_params['profile'] = profile - config = Config(user_provided_params, config_from_disk, default_params) - session = create_botocore_session(profile=config.profile, debug=debug) +def deploy(ctx, autogen_policy, profile, stage): + config = create_config_obj( + ctx, stage_name=stage, autogen_policy=autogen_policy, + profile=profile) + session = create_botocore_session(profile=config.profile, + debug=ctx.obj['debug']) d = deployer.create_default_deployer(session=session, prompter=click) try: d.deploy(config) @@ -193,32 +195,14 @@ def deploy(ctx, project_dir, autogen_policy, profile, debug, stage): @cli.command() -@click.option('--project-dir', - help='The project directory. Defaults to CWD') @click.option('--num-entries', default=None, type=int, help='Max number of log entries to show.') @click.option('--include-lambda-messages/--no-include-lambda-messages', default=False, help='Controls whether or not lambda log messages are included.') @click.pass_context -def logs(ctx, project_dir, num_entries, include_lambda_messages): - user_provided_params = {} - default_params = {} - if project_dir is None: - project_dir = os.getcwd() - default_params['project_dir'] = project_dir - else: - user_provided_params['project_dir'] = project_dir - os.chdir(project_dir) - try: - config_from_disk = load_project_config(project_dir) - except (OSError, IOError): - click.echo("Unable to load the project config file. " - "Are you sure this is a chalice project?") - raise click.Abort() - app_obj = load_chalice_app(project_dir) - user_provided_params['chalice_app'] = app_obj - config = Config(user_provided_params, config_from_disk, default_params) +def logs(ctx, num_entries, include_lambda_messages): + config = create_config_obj(ctx) show_lambda_logs(config, num_entries, include_lambda_messages) @@ -229,8 +213,7 @@ def logs(ctx, project_dir, num_entries, include_lambda_messages): def gen_policy(ctx, filename): from chalice import policy if filename is None: - project_dir = os.getcwd() - filename = os.path.join(project_dir, 'app.py') + filename = os.path.join(ctx.obj['project_dir'], 'app.py') if not os.path.isfile(filename): click.echo("App file does not exist: %s" % filename) raise click.Abort() @@ -243,8 +226,7 @@ def gen_policy(ctx, filename): @cli.command('new-project') @click.argument('project_name', required=False) @click.option('--profile', required=False) -@click.pass_context -def new_project(ctx, project_name, profile): +def new_project(project_name, profile): if project_name is None: project_name = prompts.getting_started_prompt(click) if os.path.isdir(project_name): @@ -261,7 +243,7 @@ def new_project(ctx, project_name, profile): cfg['profile'] = profile with open(config, 'w') as f: f.write(json.dumps(cfg, indent=2)) - with open(os.path.join(project_name, 'requirements.txt'), 'w') as f: + with open(os.path.join(project_name, 'requirements.txt'), 'w'): pass with open(os.path.join(project_name, 'app.py'), 'w') as f: f.write(TEMPLATE_APP % project_name) @@ -269,6 +251,23 @@ def new_project(ctx, project_name, profile): f.write(GITIGNORE) +@cli.command('url') +@click.pass_context +def url(ctx): + config = create_config_obj(ctx) + session = create_botocore_session(profile=config.profile, + debug=ctx.obj['debug']) + from chalice.awsclient import TypedAWSClient + c = TypedAWSClient(session) + rest_api_id = c.get_rest_api_id(config.app_name) + stage_name = config.stage + region_name = c.region_name + click.echo( + "https://{api_id}.execute-api.{region}.amazonaws.com/{stage}/" + .format(api_id=rest_api_id, region=region_name, stage=stage_name) + ) + + def run_local_server(app_obj): from chalice import local server = local.LocalDevServer(app_obj) diff --git a/chalice/config.py b/chalice/config.py index 2d475428d..fd0b0a375 100644 --- a/chalice/config.py +++ b/chalice/config.py @@ -34,8 +34,8 @@ def app_name(self): return self._chain_lookup('app_name') @property - def stage_name(self): - return self._chain_lookup('stage_name') + def stage(self): + return self._chain_lookup('stage') @property def manage_iam_role(self): diff --git a/chalice/deployer.py b/chalice/deployer.py index 811961fde..4a7c443b1 100644 --- a/chalice/deployer.py +++ b/chalice/deployer.py @@ -783,7 +783,7 @@ def _create_resources_for_api(self, config, rest_api_id): route_builder.build_resources(url_trie) # And finally, you need an actual deployment to deploy the changes to # API gateway. - stage = config.stage_name or 'dev' + stage = config.stage or 'dev' print "Deploying to:", stage self._aws_client.deploy_rest_api(rest_api_id, stage) return rest_api_id, self._aws_client.region_name, stage