Skip to content

Commit 5c8a21e

Browse files
authored
Merge pull request #518 from rstudio/sagerb-conflicting-params
Improve the error output for conflicting params and provide better option help describing environment variables used
2 parents b583723 + 3e4ce53 commit 5c8a21e

File tree

10 files changed

+427
-122
lines changed

10 files changed

+427
-122
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## Pending Next Release
8+
9+
### Added
10+
- Added the name of the environment variables to the help output for those options that
11+
use environment variables as a default value.
12+
13+
### Changed
14+
- Improved the error and warning outputs when options conflict by providing the source
15+
from which the values have been determined. This allows for faster resolution of issues
16+
when combinations of stored credentials, environment variables and command line options
17+
are used.
18+
- Updated verbose mode to output the source of all options being used when processing the
19+
CLI command.
20+
721
## [1.21.0] - 2023-10-26
822

923
### Fixed
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
FROM cypress/included:12.7.0
22

33
RUN apt-get update -y && apt-get install -y --no-install-recommends \
4-
jq
4+
jq \
5+
curl
56

67
RUN mkdir -p /libs-cypress && \
78
curl -fsSL https://github.com/casey/just/releases/download/1.1.2/just-1.1.2-x86_64-unknown-linux-musl.tar.gz \
@@ -10,4 +11,4 @@ RUN mkdir -p /libs-cypress && \
1011
ENV ADMIN_API_KEY=${ADMIN_API_KEY}
1112
ENV PATH=$PATH:/libs-cypress
1213
CMD cypress run --browser chrome --env api_key=${ADMIN_API_KEY}
13-
# CMD run cypress:open --env api_key=${ADMIN_API_KEY}
14+
# CMD run cypress:open --env api_key=${ADMIN_API_KEY}

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies = [
1313
"pip>=10.0.0",
1414
"semver>=2.0.0,<3.0.0",
1515
"pyjwt>=2.4.0",
16+
"click>=8.0.0",
1617
]
1718

1819
dynamic = ["version"]
@@ -33,9 +34,9 @@ test = [
3334
"pytest-cov",
3435
"pytest-mypy",
3536
"pytest",
36-
"setuptools_scm[toml]",
37+
"setuptools>=61",
38+
"setuptools_scm[toml]>=3.4",
3739
"twine",
38-
"types-click",
3940
"types-Flask",
4041
"types-six",
4142
]

requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ wheel
1010

1111
# project.dependencies
1212
six>=1.14.0
13-
click>=7.0.0
13+
click>=8.0.0
1414
pip>=10.0.0
1515
semver>=2.0.0,<3.0.0
1616
pyjwt>=2.4.0
@@ -29,6 +29,5 @@ pytest-mypy
2929
pytest
3030
setuptools_scm[toml]
3131
twine
32-
types-click
3332
types-Flask
3433
types-six

rsconnect/api.py

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import re
2020
from warnings import warn
2121
import gc
22+
import click
2223

2324
from . import validation
2425
from .certificates import read_certificate_file
@@ -389,6 +390,7 @@ def output_task_log(task_status, last_status, log_callback):
389390
class RSConnectExecutor:
390391
def __init__(
391392
self,
393+
ctx: click.Context = None,
392394
name: str = None,
393395
url: str = None,
394396
api_key: str = None,
@@ -406,7 +408,9 @@ def __init__(
406408
self.reset()
407409
self._d = kwargs
408410
self.logger = logger
411+
self.ctx = ctx
409412
self.setup_remote_server(
413+
ctx=ctx,
410414
name=name,
411415
url=url or kwargs.get("server"),
412416
api_key=api_key,
@@ -442,8 +446,31 @@ def drop_context(self):
442446
gc.collect()
443447
return self
444448

449+
def output_overlap_header(self, previous):
450+
if self.logger and not previous:
451+
self.logger.warning(
452+
"\nConnect detected CLI commands and/or environment variables that overlap with stored credential.\n"
453+
)
454+
self.logger.warning(
455+
"Check your environment variables (e.g. CONNECT_API_KEY) to make sure you want them to be used.\n"
456+
)
457+
self.logger.warning(
458+
"Credential parameters are taken with the following precedence: stored > CLI > environment.\n"
459+
)
460+
self.logger.warning(
461+
"To ignore an environment variable, override it in the CLI with an empty string (e.g. -k '').\n\n"
462+
)
463+
return True
464+
465+
def output_overlap_details(self, cli_param, previous):
466+
new_previous = self.output_overlap_header(previous)
467+
sourceName = validation.get_parameter_source_name_from_ctx(cli_param, self.ctx)
468+
self.logger.warning(f">> stored {cli_param} value overrides the {cli_param} value from {sourceName}\n")
469+
return new_previous
470+
445471
def setup_remote_server(
446472
self,
473+
ctx: click.Context,
447474
name: str = None,
448475
url: str = None,
449476
api_key: str = None,
@@ -455,6 +482,7 @@ def setup_remote_server(
455482
secret: str = None,
456483
):
457484
validation.validate_connection_options(
485+
ctx=ctx,
458486
url=url,
459487
api_key=api_key,
460488
insecure=insecure,
@@ -464,45 +492,37 @@ def setup_remote_server(
464492
secret=secret,
465493
name=name,
466494
)
495+
header_output = False
467496

468497
if cacert and not ca_data:
469498
ca_data = read_certificate_file(cacert)
470499

471500
server_data = ServerStore().resolve(name, url)
472501
if server_data.from_store:
473502
url = server_data.url
474-
if (
475-
server_data.api_key
476-
and api_key
477-
or server_data.insecure
478-
and insecure
479-
or server_data.ca_data
480-
and ca_data
481-
or server_data.account_name
482-
and account_name
483-
or server_data.token
484-
and token
485-
or server_data.secret
486-
and secret
487-
) and self.logger:
488-
self.logger.warning(
489-
"Connect detected CLI commands and/or environment variables that overlap with stored credential.\n"
490-
)
491-
self.logger.warning(
492-
"Check your environment variables (e.g. CONNECT_API_KEY) to make sure you want them to be used.\n"
493-
)
494-
self.logger.warning(
495-
"Credential paremeters are taken with the following precedence: stored > CLI > environment.\n"
496-
)
497-
self.logger.warning(
498-
"To ignore an environment variable, override it in the CLI with an empty string (e.g. -k '').\n"
499-
)
503+
if self.logger:
504+
if server_data.api_key and api_key:
505+
header_output = self.output_overlap_details("api-key", header_output)
506+
if server_data.insecure and insecure:
507+
header_output = self.output_overlap_details("insecure", header_output)
508+
if server_data.ca_data and ca_data:
509+
header_output = self.output_overlap_details("cacert", header_output)
510+
if server_data.account_name and account_name:
511+
header_output = self.output_overlap_details("account", header_output)
512+
if server_data.token and token:
513+
header_output = self.output_overlap_details("token", header_output)
514+
if server_data.secret and secret:
515+
header_output = self.output_overlap_details("secret", header_output)
516+
if header_output:
517+
self.logger.warning("\n")
518+
500519
api_key = server_data.api_key or api_key
501520
insecure = server_data.insecure or insecure
502521
ca_data = server_data.ca_data or ca_data
503522
account_name = server_data.account_name or account_name
504523
token = server_data.token or token
505524
secret = server_data.secret or secret
525+
506526
self.is_server_from_store = server_data.from_store
507527

508528
if api_key:
@@ -571,7 +591,7 @@ def validate_connect_server(
571591
:param url: the URL, if any, specified by the user.
572592
:param api_key: the API key, if any, specified by the user.
573593
:param insecure: a flag noting whether TLS host/validation should be skipped.
574-
:param cacert: the file object of a CA certs file containing certificates to use.
594+
:param cacert: the file path of a CA certs file containing certificates to use.
575595
:param api_key_is_required: a flag that notes whether the API key is required or may
576596
be omitted.
577597
:param token: The shinyapps.io authentication token.

rsconnect/certificates.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ def read_certificate_file(location: str):
2121
suffix = path.suffix
2222

2323
if suffix in BINARY_ENCODED_FILETYPES:
24-
with open(path, "rb") as file:
25-
return file.read()
24+
with open(path, "rb") as bFile:
25+
return bFile.read()
2626

2727
if suffix in TEXT_ENCODED_FILETYPES:
28-
with open(path, "r") as file:
29-
return file.read()
28+
with open(path, "r") as tFile:
29+
return tFile.read()
3030

3131
types = BINARY_ENCODED_FILETYPES + TEXT_ENCODED_FILETYPES
3232
types = sorted(types)

0 commit comments

Comments
 (0)