def delete_and_rm_options(*args, **kwargs): """ Options which apply both to `globus delete` and `globus rm` """ def inner_decorator(f, supports_batch=True, default_enable_globs=False): f = click.option( '--recursive', '-r', is_flag=True, help='Recursively delete dirs')(f) f = click.option( '--ignore-missing', '-f', is_flag=True, help="Don't throw errors if the file or dir is absent")(f) f = click.option( '--star-silent', '--unsafe', 'star_silent', is_flag=True, help=("Don't prompt when the trailing character is a \"*\"." + (" Implicit in --batch" if supports_batch else "")))(f) f = click.option( '--enable-globs/--no-enable-globs', is_flag=True, default=default_enable_globs, show_default=True, help=("Enable expansion of *, ?, and [ ] characters in the last " "component of file paths, unless they are escaped with " "a preceeding backslash, \\"))(f) if supports_batch: f = click.option( '--batch', is_flag=True, help=('Accept a batch of paths on stdin (i.e. run in ' 'batchmode). Uses ENDPOINT_ID as passed on the ' 'commandline. Any commandline PATH given will be used ' 'as a prefix to all paths given'))(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def endpoint_id_arg(*args, **kwargs): """ This is the `ENDPOINT_ID` argument consumed by many Transfer endpoint related operations. It accepts alternate metavars for cases when another name is desirable (e.x. `SHARE_ID`, `HOST_ENDPOINT_ID`), but can also be applied as a direct decorator if no specialized metavar is being passed. Usage: >>> @endpoint_id_arg >>> def command_func(endpoint_id): >>> ... or >>> @endpoint_id_arg(metavar='HOST_ENDPOINT_ID') >>> def command_func(endpoint_id): >>> ... """ def decorate(f, **kwargs): """ Work of actually decorating a function -- wrapped in here because we want to dispatch depending on how this is invoked """ metavar = kwargs.get('metavar', 'ENDPOINT_ID') f = click.argument('endpoint_id', metavar=metavar, type=click.UUID)(f) return f return detect_and_decorate(decorate, args, kwargs)
def task_id_arg(*args, **kwargs): """ This is the `TASK_ID` argument consumed by many Transfer Task operations. It accept a toggle on whether or not it is required Usage: >>> @task_id_option >>> def command_func(task_id): >>> ... or >>> @task_id_option(required=False) >>> def command_func(task_id): >>> ... By default, the task ID is made required; pass `required=False` to the decorator arguments to make it optional. """ def inner_decorator(f, required=True): f = click.argument('TASK_ID', required=required)(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def endpoint_id_arg(*args, **kwargs): """ This is the `ENDPOINT_ID` argument consumed by many Transfer endpoint related operations. It accepts alternate metavars for cases when another name is desirable (e.x. `SHARE_ID`, `HOST_ENDPOINT_ID`), but can also be applied as a direct decorator if no specialized metavar is being passed. Usage: >>> @endpoint_id_arg >>> def command_func(endpoint_id): >>> ... or >>> @endpoint_id_arg(metavar='HOST_ENDPOINT_ID') >>> def command_func(endpoint_id): >>> ... """ def decorate(f, **kwargs): """ Work of actually decorating a function -- wrapped in here because we want to dispatch depending on how this is invoked """ metavar = kwargs.get("metavar", "ENDPOINT_ID") f = click.argument("endpoint_id", metavar=metavar, type=click.UUID)(f) return f return detect_and_decorate(decorate, args, kwargs)
def task_id_arg(*args, **kwargs): """ This is the `TASK_ID` argument consumed by many Transfer Task operations. It accept a toggle on whether or not it is required Usage: >>> @task_id_option >>> def command_func(task_id): >>> ... or >>> @task_id_option(required=False) >>> def command_func(task_id): >>> ... By default, the task ID is made required; pass `required=False` to the decorator arguments to make it optional. """ def inner_decorator(f, required=True): f = click.argument("TASK_ID", required=required)(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def delete_and_rm_options(*args, **kwargs): """ Options which apply both to `globus delete` and `globus rm` """ def inner_decorator(f, supports_batch=True, default_enable_globs=False): f = click.option( "--recursive", "-r", is_flag=True, help="Recursively delete dirs" )(f) f = click.option( "--ignore-missing", "-f", is_flag=True, help="Don't throw errors if the file or dir is absent", )(f) f = click.option( "--star-silent", "--unsafe", "star_silent", is_flag=True, help=( 'Don\'t prompt when the trailing character is a "*".' + (" Implicit in --batch" if supports_batch else "") ), )(f) f = click.option( "--enable-globs/--no-enable-globs", is_flag=True, default=default_enable_globs, show_default=True, help=( "Enable expansion of *, ?, and [ ] characters in the last " "component of file paths, unless they are escaped with " "a preceeding backslash, \\" ), )(f) if supports_batch: f = click.option( "--batch", is_flag=True, help=( "Accept a batch of paths on stdin (i.e. run in " "batchmode). Uses ENDPOINT_ID as passed on the " "commandline. Any commandline PATH given will be used " "as a prefix to all paths given" ), )(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def common_options(*args, **kwargs): """ This is a multi-purpose decorator for applying a "base" set of options shared by all commands. It can be applied either directly, or given keyword arguments. Usage: >>> @common_options >>> def mycommand(abc, xyz): >>> ... or >>> @common_options(disable_options=["format"]) >>> def mycommand(abc, xyz): >>> ... to disable use of `--format` """ disable_opts = kwargs.get("disable_options", []) def decorate(f, **kwargs): """ Work of actually decorating a function -- wrapped in here because we want to dispatch depending on how `common_options` is invoked """ f = version_option(f) f = debug_option(f) f = verbose_option(f) f = click.help_option("-h", "--help")(f) # if the format option is being allowed, it needs to be applied to `f` if "format" not in disable_opts: f = format_option(f) # if the --map-http-status option is being allowed, ... if "map_http_status" not in disable_opts: f = map_http_status_option(f) return f return detect_and_decorate(decorate, args, kwargs)
def common_options(*args, **kwargs): """ This is a multi-purpose decorator for applying a "base" set of options shared by all commands. It can be applied either directly, or given keyword arguments. Usage: >>> @common_options >>> def mycommand(abc, xyz): >>> ... or >>> @common_options(no_format_option=True) >>> def mycommand(abc, xyz): >>> ... """ def decorate(f, **kwargs): """ Work of actually decorating a function -- wrapped in here because we want to dispatch depending on how `common_options` is invoked """ f = version_option(f) f = debug_option(f) f = verbose_option(f) f = click.help_option("-h", "--help")(f) # if the format option is being allowed, it needs to be applied to `f` if not kwargs.get("no_format_option"): f = format_option(f) # if the --map-http-status option is being allowed, ... if not kwargs.get("no_map_http_status_option"): f = map_http_status_option(f) return f return detect_and_decorate(decorate, args, kwargs)
def endpoint_create_and_update_params(*args, **kwargs): """ Collection of options consumed by Transfer endpoint create and update operations -- accepts toggle regarding create vs. update that makes display_name required vs. optional. Usage: >>> @endpoint_create_and_update_params(create=True) >>> def command_func(display_name, description, info_link, contact_info, >>> contact_email, organization, department, keywords, >>> public, location, disable_verify, myproxy_dn, >>> myproxy_server, oauth_server, force_encryption, >>> default_directory, subscription_id, network_use, >>> max_concurrency, preferred_concurrency, >>> max_parallelism, preferred_parallelism): >>> ... """ def inner_decorator(f, create=False): update_help_prefix = (not create and 'New ') or '' # display name is required for create, not update if create: f = click.argument('display_name')(f) else: f = click.option('--display-name', help=(update_help_prefix + 'Name for the endpoint'))(f) # Options available to any endpoint f = click.option("--description", help=(update_help_prefix + "Description for the endpoint"))(f) f = click.option("--info-link", help=(update_help_prefix + "Link for Info about the endpoint"))(f) f = click.option("--contact-info", help=(update_help_prefix + "Contact Info for the endpoint"))(f) f = click.option("--contact-email", help=(update_help_prefix + "Contact Email for the endpoint"))(f) f = click.option("--organization", help=(update_help_prefix + "Organization for the endpoint"))(f) f = click.option("--department", help=(update_help_prefix + "Department which operates the endpoint"))(f) f = click.option( "--keywords", help=(update_help_prefix + "Comma separated list of keywords to help searches " "for the endpoint"))(f) f = click.option("--default-directory", help=("Set the default directory"))(f) f = click.option( "--no-default-directory", is_flag=True, flag_value=True, default=None, help=("Unset any default directory on the endpoint"))(f) f = click.option( "--force-encryption/--no-force-encryption", default=None, help=("(Un)Force the endpoint to encrypt transfers"))(f) f = click.option( "--disable-verify/--no-disable-verify", is_flag=True, help="(Un)Set the endpoint to ignore checksum verification")(f) # GCS only options f = click.option("--public/--private", "public", default=None, help=("Set the endpoint to be public or private " "(Globus Connect Server only)"))(f) f = click.option( "--myproxy-dn", help=("Set the MyProxy Server DN (Globus Connect Server only)"))(f) f = click.option("--myproxy-server", help=("Set the MyProxy Server URI " "(Globus Connect Server only)"))(f) f = click.option( "--oauth-server", help=("Set the OAuth Server URI (Globus Connect Server only)"))(f) f = click.option( "--location", type=LocationType(), default=None, help="Manually set the endpoint's latitude and longitude " "(Globus Connect Server only)")(f) # Managed Endpoint options f = click.option( "--managed", "managed", is_flag=True, flag_value=True, default=None, help=("Set the endpoint as a managed endpoint. Requires the " "user to be a subscription manager. If the user has " "multiple subscription IDs, --subscription-id must be used " "instead"))(f) f = click.option( "--no-managed", "managed", is_flag=True, flag_value=False, default=None, help=("Unset the endpoint as a managed endpoint. " "Does not require the user to be a subscription manager. " "Mutually exclusive with --subscription-id"))(f) f = click.option( "--subscription-id", type=click.UUID, default=None, help=("Set the endpoint as a managed endpoint with the given " "subscription ID. Mutually exclusive with " "--no-managed"))(f) f = click.option( "--network-use", default=None, type=click.Choice(["normal", "minimal", "aggressive", "custom"]), help=("Set the endpoint's network use level. If using custom, " "the endpoint's max and preferred concurrency and " "parallelism must be set " "(Managed endpoints only) (Globus Connect Server only)"))(f) f = click.option( "--max-concurrency", type=int, default=None, help=("Set the endpoint's max concurrency; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)"))(f) f = click.option( "--preferred-concurrency", type=int, default=None, help=("Set the endpoint's preferred concurrency; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)"))(f) f = click.option( "--max-parallelism", type=int, default=None, help=("Set the endpoint's max parallelism; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)"))(f) f = click.option( "--preferred-parallelism", type=int, default=None, help=("Set the endpoint's preferred parallelism; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)"))(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def security_principal_opts(*args, **kwargs): def preprocess_security_principals(f): def decorator(*args, **kwargs): identity = kwargs.pop('identity', None) group = kwargs.pop('group', None) provision_identity = kwargs.pop('provision_identity', None) has_identity = (identity or provision_identity) if identity and provision_identity: raise click.UsageError( 'Only one of --identity or --provision-identity ' 'allowed') if kwargs.get('principal') is not None: if has_identity or group: raise click.UsageError( 'You may only pass one security principal') else: if has_identity and group: raise click.UsageError( ('You have passed both an identity and a group. ' 'Please only pass one principal type')) elif not has_identity and not group: raise click.UsageError( ('You must provide at least one principal ' '(identity, group, etc.)')) if identity: kwargs['principal'] = ('identity', identity) elif provision_identity: kwargs['principal'] = ('provision-identity', provision_identity) else: kwargs['principal'] = ('group', group) return f(*args, **kwargs) return decorator def inner_decorator(f, allow_anonymous=False, allow_all_authenticated=False, allow_provision=False): # order matters here -- the preprocessor must run after option # application, so it has to be applied first if isinstance(f, click.Command): # if we're decorating a command, put the preprocessor on its # callback, not on `f` itself f.callback = preprocess_security_principals(f.callback) else: # otherwise, we're applying to a function, but other decorators may # have been applied to give it params # so, copy __click_params__ to preserve those parameters oldfun = f f = preprocess_security_principals(f) f.__click_params__ = getattr(oldfun, '__click_params__', []) f = click.option('--identity', metavar='IDENTITY_ID_OR_NAME', help='Identity to use as a security principal')(f) f = click.option('--group', metavar='GROUP_ID', help='Group to use as a security principal')(f) if allow_anonymous: f = click.option( '--anonymous', 'principal', flag_value=('anonymous', ""), help=('Allow anyone access, even without logging in ' '(treated as a security principal)'))(f) if allow_all_authenticated: f = click.option('--all-authenticated', 'principal', flag_value=('all_authenticated_users', ""), help=('Allow anyone access, as long as they login' '(treated as a security principal)'))(f) if allow_provision: f = click.option( '--provision-identity', metavar='IDENTITY_USERNAME', help='Identity username to use as a security principal. ' 'Identity will be provisioned if it does not exist.')(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def server_add_and_update_opts(*args, **kwargs): """ shared collection of options for `globus transfer endpoint server add` and `globus transfer endpoint server update`. Accepts a toggle to know if it's being used as `add` or `update`. usage: >>> @server_add_and_update_opts >>> def command_func(subject, port, scheme, hostname): >>> ... or >>> @server_add_and_update_opts(add=True) >>> def command_func(subject, port, scheme, hostname): >>> ... """ def port_range_callback(ctx, param, value): if not value: return None value = value.lower().strip() if value == 'unspecified': return None, None if value == 'unrestricted': return 1024, 65535 try: lower, upper = map(int, value.split('-')) except ValueError: # too many/few values from split or non-integer(s) raise click.BadParameter("must specify as 'unspecified', " "'unrestricted', or as range separated " "by a hyphen (e.g. '50000-51000')") if not 1024 <= lower <= 65535 or not 1024 <= upper <= 65535: raise click.BadParameter("must be within the 1024-65535 range") return (lower, upper) if lower <= upper else (upper, lower) def inner_decorator(f, add=False): f = click.option('--hostname', required=add, help='Server Hostname.')(f) default_scheme = 'gsiftp' if add else None f = click.option('--scheme', help='Scheme for the Server.', type=CaseInsensitiveChoice(('gsiftp', 'ftp')), default=default_scheme, show_default=add)(f) default_port = 2811 if add else None f = click.option('--port', help='Port for Globus control channel connections.', type=int, default=default_port, show_default=add)(f) f = click.option( '--subject', help=('Subject of the X509 Certificate of the server. When ' 'unspecified, the CN must match the server hostname.'))(f) for adjective, our_preposition, their_preposition in [ ('incoming', 'to', 'from'), ('outgoing', 'from', 'to'), ]: f = click.option( '--{}-data-ports'.format(adjective), callback=port_range_callback, help="Indicate to firewall administrators at other sites how to " "allow {} traffic {} this server {} their own. Specify as " "either 'unspecified', 'unrestricted', or as range of " "ports separated by a hyphen (e.g. '50000-51000') within " "the 1024-65535 range.".format(adjective, our_preposition, their_preposition))(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def security_principal_opts(*args, **kwargs): def preprocess_security_principals(f): def decorator(*args, **kwargs): identity = kwargs.pop("identity", None) group = kwargs.pop("group", None) provision_identity = kwargs.pop("provision_identity", None) has_identity = identity or provision_identity if identity and provision_identity: raise click.UsageError( "Only one of --identity or --provision-identity " "allowed") if kwargs.get("principal") is not None: if has_identity or group: raise click.UsageError( "You may only pass one security principal") else: if has_identity and group: raise click.UsageError( ("You have passed both an identity and a group. " "Please only pass one principal type")) elif not has_identity and not group: raise click.UsageError( ("You must provide at least one principal " "(identity, group, etc.)")) if identity: kwargs["principal"] = ("identity", identity) elif provision_identity: kwargs["principal"] = ("provision-identity", provision_identity) else: kwargs["principal"] = ("group", group) return f(*args, **kwargs) return decorator def inner_decorator(f, allow_anonymous=False, allow_all_authenticated=False, allow_provision=False): # order matters here -- the preprocessor must run after option # application, so it has to be applied first if isinstance(f, click.Command): # if we're decorating a command, put the preprocessor on its # callback, not on `f` itself f.callback = preprocess_security_principals(f.callback) else: # otherwise, we're applying to a function, but other decorators may # have been applied to give it params # so, copy __click_params__ to preserve those parameters oldfun = f f = preprocess_security_principals(f) f.__click_params__ = getattr(oldfun, "__click_params__", []) f = click.option( "--identity", metavar="IDENTITY_ID_OR_NAME", help="Identity to use as a security principal", )(f) f = click.option("--group", metavar="GROUP_ID", help="Group to use as a security principal")(f) if allow_anonymous: f = click.option( "--anonymous", "principal", flag_value=("anonymous", ""), help=("Allow anyone access, even without logging in " "(treated as a security principal)"), )(f) if allow_all_authenticated: f = click.option( "--all-authenticated", "principal", flag_value=("all_authenticated_users", ""), help=("Allow anyone access, as long as they login" "(treated as a security principal)"), )(f) if allow_provision: f = click.option( "--provision-identity", metavar="IDENTITY_USERNAME", help="Identity username to use as a security principal. " "Identity will be provisioned if it does not exist.", )(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def endpoint_create_and_update_params(*args, **kwargs): """ Collection of options consumed by Transfer endpoint create and update operations -- accepts toggle regarding create vs. update that makes display_name required vs. optional. Usage: >>> @endpoint_create_and_update_params(create=True) >>> def command_func(display_name, description, info_link, contact_info, >>> contact_email, organization, department, keywords, >>> public, location, disable_verify, myproxy_dn, >>> myproxy_server, oauth_server, force_encryption, >>> default_directory, subscription_id, network_use, >>> max_concurrency, preferred_concurrency, >>> max_parallelism, preferred_parallelism): >>> ... """ def inner_decorator(f, create=False): update_help_prefix = (not create and "New ") or "" # display name is required for create, not update if create: f = click.argument("display_name")(f) else: f = click.option( "--display-name", help=(update_help_prefix + "Name for the endpoint") )(f) # Options available to any endpoint f = click.option( "--description", help=(update_help_prefix + "Description for the endpoint") )(f) f = click.option( "--info-link", help=(update_help_prefix + "Link for Info about the endpoint"), )(f) f = click.option( "--contact-info", help=(update_help_prefix + "Contact Info for the endpoint"), )(f) f = click.option( "--contact-email", help=(update_help_prefix + "Contact Email for the endpoint"), )(f) f = click.option( "--organization", help=(update_help_prefix + "Organization for the endpoint"), )(f) f = click.option( "--department", help=(update_help_prefix + "Department which operates the endpoint"), )(f) f = click.option( "--keywords", help=( update_help_prefix + "Comma separated list of keywords to help searches " "for the endpoint" ), )(f) f = click.option("--default-directory", help=("Set the default directory"))(f) f = click.option( "--no-default-directory", is_flag=True, flag_value=True, default=None, help=("Unset any default directory on the endpoint"), )(f) f = click.option( "--force-encryption/--no-force-encryption", default=None, help=("(Un)Force the endpoint to encrypt transfers"), )(f) f = click.option( "--disable-verify/--no-disable-verify", is_flag=True, help="(Un)Set the endpoint to ignore checksum verification", )(f) # GCS only options f = click.option( "--public/--private", "public", default=None, help=( "Set the endpoint to be public or private " "(Globus Connect Server only)" ), )(f) f = click.option( "--myproxy-dn", help=("Set the MyProxy Server DN (Globus Connect Server only)"), )(f) f = click.option( "--myproxy-server", help=("Set the MyProxy Server URI " "(Globus Connect Server only)"), )(f) f = click.option( "--oauth-server", help=("Set the OAuth Server URI (Globus Connect Server only)"), )(f) f = click.option( "--location", type=LocationType(), default=None, help="Manually set the endpoint's latitude and longitude " "(Globus Connect Server only)", )(f) # Managed Endpoint options f = click.option( "--managed", "managed", is_flag=True, flag_value=True, default=None, help=( "Set the endpoint as a managed endpoint. Requires the " "user to be a subscription manager. If the user has " "multiple subscription IDs, --subscription-id must be used " "instead" ), )(f) f = click.option( "--no-managed", "managed", is_flag=True, flag_value=False, default=None, help=( "Unset the endpoint as a managed endpoint. " "Does not require the user to be a subscription manager. " "Mutually exclusive with --subscription-id" ), )(f) f = click.option( "--subscription-id", type=click.UUID, default=None, help=( "Set the endpoint as a managed endpoint with the given " "subscription ID. Mutually exclusive with " "--no-managed" ), )(f) f = click.option( "--network-use", default=None, type=click.Choice(["normal", "minimal", "aggressive", "custom"]), help=( "Set the endpoint's network use level. If using custom, " "the endpoint's max and preferred concurrency and " "parallelism must be set " "(Managed endpoints only) (Globus Connect Server only)" ), )(f) f = click.option( "--max-concurrency", type=int, default=None, help=( "Set the endpoint's max concurrency; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)" ), )(f) f = click.option( "--preferred-concurrency", type=int, default=None, help=( "Set the endpoint's preferred concurrency; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)" ), )(f) f = click.option( "--max-parallelism", type=int, default=None, help=( "Set the endpoint's max parallelism; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)" ), )(f) f = click.option( "--preferred-parallelism", type=int, default=None, help=( "Set the endpoint's preferred parallelism; " "requires --network-use=custom " "(Managed endpoints only) (Globus Connect Server only)" ), )(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def security_principal_opts(*args, **kwargs): def preprocess_security_principals(f): def decorator(*args, **kwargs): identity = kwargs.pop("identity", None) group = kwargs.pop("group", None) provision_identity = kwargs.pop("provision_identity", None) has_identity = identity or provision_identity if identity and provision_identity: raise click.UsageError( "Only one of --identity or --provision-identity " "allowed" ) if kwargs.get("principal") is not None: if has_identity or group: raise click.UsageError("You may only pass one security principal") else: if has_identity and group: raise click.UsageError( ( "You have passed both an identity and a group. " "Please only pass one principal type" ) ) elif not has_identity and not group: raise click.UsageError( ( "You must provide at least one principal " "(identity, group, etc.)" ) ) if identity: kwargs["principal"] = ("identity", identity) elif provision_identity: kwargs["principal"] = ("provision-identity", provision_identity) else: kwargs["principal"] = ("group", group) return f(*args, **kwargs) return decorator def inner_decorator( f, allow_anonymous=False, allow_all_authenticated=False, allow_provision=False ): # order matters here -- the preprocessor must run after option # application, so it has to be applied first if isinstance(f, click.Command): # if we're decorating a command, put the preprocessor on its # callback, not on `f` itself f.callback = preprocess_security_principals(f.callback) else: # otherwise, we're applying to a function, but other decorators may # have been applied to give it params # so, copy __click_params__ to preserve those parameters oldfun = f f = preprocess_security_principals(f) f.__click_params__ = getattr(oldfun, "__click_params__", []) f = click.option( "--identity", metavar="IDENTITY_ID_OR_NAME", help="Identity to use as a security principal", )(f) f = click.option( "--group", metavar="GROUP_ID", help="Group to use as a security principal" )(f) if allow_anonymous: f = click.option( "--anonymous", "principal", flag_value=("anonymous", ""), help=( "Allow anyone access, even without logging in " "(treated as a security principal)" ), )(f) if allow_all_authenticated: f = click.option( "--all-authenticated", "principal", flag_value=("all_authenticated_users", ""), help=( "Allow anyone access, as long as they login" "(treated as a security principal)" ), )(f) if allow_provision: f = click.option( "--provision-identity", metavar="IDENTITY_USERNAME", help="Identity username to use as a security principal. " "Identity will be provisioned if it does not exist.", )(f) return f return detect_and_decorate(inner_decorator, args, kwargs)
def server_add_and_update_opts(*args, **kwargs): """ shared collection of options for `globus transfer endpoint server add` and `globus transfer endpoint server update`. Accepts a toggle to know if it's being used as `add` or `update`. usage: >>> @server_add_and_update_opts >>> def command_func(subject, port, scheme, hostname): >>> ... or >>> @server_add_and_update_opts(add=True) >>> def command_func(subject, port, scheme, hostname): >>> ... """ def port_range_callback(ctx, param, value): if not value: return None value = value.lower().strip() if value == "unspecified": return None, None if value == "unrestricted": return 1024, 65535 try: lower, upper = map(int, value.split("-")) except ValueError: # too many/few values from split or non-integer(s) raise click.BadParameter( "must specify as 'unspecified', " "'unrestricted', or as range separated " "by a hyphen (e.g. '50000-51000')" ) if not 1024 <= lower <= 65535 or not 1024 <= upper <= 65535: raise click.BadParameter("must be within the 1024-65535 range") return (lower, upper) if lower <= upper else (upper, lower) def inner_decorator(f, add=False): f = click.option("--hostname", required=add, help="Server Hostname.")(f) default_scheme = "gsiftp" if add else None f = click.option( "--scheme", help="Scheme for the Server.", type=CaseInsensitiveChoice(("gsiftp", "ftp")), default=default_scheme, show_default=add, )(f) default_port = 2811 if add else None f = click.option( "--port", help="Port for Globus control channel connections.", type=int, default=default_port, show_default=add, )(f) f = click.option( "--subject", help=( "Subject of the X509 Certificate of the server. When " "unspecified, the CN must match the server hostname." ), )(f) for adjective, our_preposition, their_preposition in [ ("incoming", "to", "from"), ("outgoing", "from", "to"), ]: f = click.option( "--{}-data-ports".format(adjective), callback=port_range_callback, help="Indicate to firewall administrators at other sites how to " "allow {} traffic {} this server {} their own. Specify as " "either 'unspecified', 'unrestricted', or as range of " "ports separated by a hyphen (e.g. '50000-51000') within " "the 1024-65535 range.".format( adjective, our_preposition, their_preposition ), )(f) return f return detect_and_decorate(inner_decorator, args, kwargs)