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

Operations/methods missing paginators #1462

Closed
kapilt opened this issue May 12, 2018 · 16 comments
Closed

Operations/methods missing paginators #1462

kapilt opened this issue May 12, 2018 · 16 comments
Assignees
Labels
feature-request This issue requests a feature. p2 This is a standard priority issue paginator

Comments

@kapilt
Copy link
Contributor

kapilt commented May 12, 2018

I brought this up at the openspace at pycon, there are lots of client methods missing paginator metadata. I went ahead and coded up simple script to identify all the missing paginators in botocore json sdk metadata.

import boto3
import yaml

def main():
    session = boto3.Session()
    services = session.get_available_services()
    op_missing_paginator = {}
    for s in services:
        c = session.client(s)
        op_to_py = {v: k for k, v in c._PY_TO_OP_NAME.items()}
        for op in c.meta.service_model.operation_names:
            opm = c.meta.service_model.operation_model(op)
            if opm.output_shape is None:
                continue
            if 'NextToken' not in opm.output_shape.members:
                continue
            py_name = op_to_py[opm.name]
            if not c.can_paginate(py_name):
                op_missing_paginator.setdefault(s, []).append(py_name)
    print(yaml.safe_dump(op_missing_paginator, default_flow_style=False))

Which results in the following output

acm-pca:
- list_certificate_authorities
- list_tags
alexaforbusiness:
- list_device_events
- search_address_books
- search_contacts
application-autoscaling:
- describe_scheduled_actions
appstream:
- describe_directory_configs
- describe_fleets
- describe_image_builders
- describe_sessions
- describe_stacks
- list_associated_fleets
- list_associated_stacks
autoscaling:
- describe_load_balancer_target_groups
- describe_load_balancers
autoscaling-plans:
- describe_scaling_plan_resources
- describe_scaling_plans
budgets:
- describe_budgets
- describe_notifications_for_budget
- describe_subscribers_for_notification
clouddirectory:
- list_incoming_typed_links
- list_object_children
- list_object_parents
- list_outgoing_typed_links
cloudformation:
- describe_account_limits
- describe_change_set
- list_change_sets
- list_stack_instances
- list_stack_set_operation_results
- list_stack_set_operations
- list_stack_sets
cloudhsm:
- list_hapgs
- list_hsms
- list_luna_clients
cloudtrail:
- list_public_keys
- list_tags
cloudwatch:
- get_metric_data
codepipeline:
- list_webhooks
cognito-identity:
- list_identities
- list_identity_pools
- lookup_developer_identity
cognito-idp:
- admin_list_groups_for_user
- admin_list_user_auth_events
- list_groups
- list_identity_providers
- list_resource_servers
- list_user_pool_clients
- list_user_pools
- list_users_in_group
cognito-sync:
- list_datasets
- list_identity_pool_usage
- list_records
config:
- describe_aggregate_compliance_by_config_rules
- describe_aggregation_authorizations
- describe_config_rule_evaluation_status
- describe_configuration_aggregator_sources_status
- describe_configuration_aggregators
- describe_pending_aggregation_requests
- get_aggregate_compliance_details_by_config_rule
- get_aggregate_config_rule_compliance_summary
dax:
- describe_clusters
- describe_default_parameters
- describe_events
- describe_parameter_groups
- describe_parameters
- describe_subnet_groups
- list_tags
ds:
- describe_directories
- describe_snapshots
- describe_trusts
- list_ip_routes
- list_schema_extensions
- list_tags_for_resource
dynamodb:
- list_tags_of_resource
ec2:
- describe_classic_link_instances
- describe_egress_only_internet_gateways
- describe_elastic_gpus
- describe_fleet_history
- describe_fleet_instances
- describe_fleets
- describe_flow_logs
- describe_fpga_images
- describe_host_reservation_offerings
- describe_host_reservations
- describe_hosts
- describe_import_image_tasks
- describe_import_snapshot_tasks
- describe_instance_credit_specifications
- describe_launch_template_versions
- describe_launch_templates
- describe_moving_addresses
- describe_network_interface_permissions
- describe_prefix_lists
- describe_principal_id_format
- describe_scheduled_instance_availability
- describe_scheduled_instances
- describe_spot_fleet_request_history
- describe_stale_security_groups
- describe_volumes_modifications
- describe_vpc_classic_link_dns_support
- describe_vpc_endpoint_connection_notifications
- describe_vpc_endpoint_connections
- describe_vpc_endpoint_service_configurations
- describe_vpc_endpoint_service_permissions
- describe_vpc_endpoint_services
- describe_vpc_endpoints
elasticbeanstalk:
- compose_environments
- describe_application_versions
- describe_environment_managed_action_history
- describe_environments
- describe_instances_health
- list_platform_versions
events:
- list_rule_names_by_target
- list_rules
- list_targets_by_rule
fms:
- list_compliance_status
- list_policies
gamelift:
- describe_fleet_attributes
- describe_fleet_capacity
- describe_fleet_events
- describe_fleet_utilization
- describe_game_session_details
- describe_game_session_queues
- describe_game_sessions
- describe_instances
- describe_matchmaking_configurations
- describe_matchmaking_rule_sets
- describe_player_sessions
- describe_scaling_policies
- list_aliases
- list_builds
- list_fleets
- search_game_sessions
greengrass:
- list_core_definition_versions
- list_core_definitions
- list_deployments
- list_device_definition_versions
- list_device_definitions
- list_function_definition_versions
- list_function_definitions
- list_group_versions
- list_groups
- list_logger_definition_versions
- list_logger_definitions
- list_resource_definition_versions
- list_resource_definitions
- list_subscription_definition_versions
- list_subscription_definitions
kinesis:
- list_shards
kinesis-video-archived-media:
- list_fragments
kinesisvideo:
- list_streams
- list_tags_for_stream
marketplace-entitlement:
- get_entitlements
mediaconvert:
- describe_endpoints
- list_job_templates
- list_jobs
- list_presets
- list_queues
mediastore:
- list_containers
mediastore-data:
- list_items
mgh:
- list_created_artifacts
- list_discovered_resources
- list_migration_tasks
- list_progress_update_streams
mq:
- list_brokers
- list_configuration_revisions
- list_configurations
- list_users
mturk:
- list_review_policy_results_for_hit
opsworks:
- list_tags
opsworkscm:
- describe_backups
- describe_events
- describe_servers
polly:
- list_lexicons
rekognition:
- get_celebrity_recognition
- get_content_moderation
- get_face_detection
- get_face_search
- get_label_detection
- get_person_tracking
route53:
- list_query_logging_configs
- list_vpc_association_authorizations
sagemaker:
- list_notebook_instance_lifecycle_configs
secretsmanager:
- list_secret_version_ids
- list_secrets
serverlessrepo:
- list_application_versions
- list_applications
servicediscovery:
- get_instances_health_status
ses:
- list_configuration_sets
- list_receipt_rule_sets
- list_templates
shield:
- list_attacks
snowball:
- list_cluster_jobs
- list_clusters
ssm:
- describe_automation_executions
- describe_automation_step_executions
- describe_available_patches
- describe_effective_instance_associations
- describe_effective_patches_for_patch_baseline
- describe_instance_associations_status
- describe_instance_patch_states
- describe_instance_patch_states_for_patch_group
- describe_instance_patches
- describe_inventory_deletions
- describe_maintenance_window_execution_task_invocations
- describe_maintenance_window_execution_tasks
- describe_maintenance_window_executions
- describe_maintenance_window_targets
- describe_maintenance_window_tasks
- describe_maintenance_windows
- describe_patch_baselines
- describe_patch_groups
- get_inventory
- get_inventory_schema
- list_association_versions
- list_compliance_items
- list_compliance_summaries
- list_document_versions
- list_inventory_entries
- list_resource_compliance_summaries
- list_resource_data_sync
transcribe:
- list_transcription_jobs
- list_vocabularies
workmail:
- list_mailbox_permissions
- list_resource_delegates
workspaces:
- describe_ip_groups
- describe_workspaces_connection_status
@joguSD
Copy link
Contributor

joguSD commented May 14, 2018

Thanks for generating this list. We need to do a little more auditing on these. Another important attribute for operations that we can support pagination for is if the operation has a list in the output (and preferably only one list). Sometimes APIs will paginate over maps or have multiple lists and this can be problematic for us as we aggregate the output on behalf of the user (this is unique to boto3/CLI in comparison to other SDKs). If anybody wants to start taking a crack at these please go ahead, ideally each service as a separate PR.

@joguSD joguSD added paginator feature-request This issue requests a feature. labels May 14, 2018
@kalyanaramansanthanam
Copy link

any ETA on when these paginators will be available?

slai added a commit to slai/botocore that referenced this issue Oct 31, 2018
This adds the missing pagination definitions for the CloudFormation APIs, as described in boto#1462.

I've tested DescribeChangeSet and ListChangeSets and both work as expected after this change,

```
client = boto3.client('cloudformation', region_name='eu-west-1')

paginator = client.get_paginator('list_change_sets')
page_iterator = paginator.paginate(StackName='MyStack')

for page in page_iterator:
    print(page)
```
@slai
Copy link
Contributor

slai commented Oct 31, 2018

slai added a commit to slai/botocore that referenced this issue Oct 31, 2018
There are currently no pagination definitions for CloudWatch Events APIs.

I've created them from the API Reference for this PR. The list of definitions now matches the API reference and also the list missing in boto#1462.

```python
client = boto3.client('events', region_name='eu-west-1')

paginator = client.get_paginator('list_rules')
page_iterator = paginator.paginate(NamePrefix='RDS', PaginationConfig={'PageSize': 2})

for page in page_iterator:
    print(page)
```
@kapilt
Copy link
Contributor Author

kapilt commented Oct 31, 2018

I’ve done one off contribs on paginators before. I suggest a holistic approach geared towards coverage, ie default generators based on this heuristic, followed with api method specific customization as needed.

@kapilt
Copy link
Contributor Author

kapilt commented Dec 8, 2018

I went ahead and extended this snippet to enable generation of paginators taking into the account additional constraints with regard to merged output fields, if I send a pr per service its on the order of 60+.. is that preferable to an individual pr?

@brandond
Copy link
Contributor

I just updated #1548 to fix a test failure. I agree that handling this at an individual service level seems prone to failure. It'd be great to have the paginator config auto-generated from the service JSON instead of being manually updated (or not, as the case may be).

@JordonPhillips
Copy link
Contributor

@kapilt I have a script that generates paginators, constrained heavily to only generate those that I can be absolutely certain about. I just merged a PR stemming from that that added a ton. What we really need to do is to have that be part of our release automation. Right now we're relying pretty much entirely on getting them from upstream.

@kapilt
Copy link
Contributor Author

kapilt commented Dec 30, 2018

@JordonPhillips thanks, one thing missing from the pr was the script used to generate afaics re #1633 which ideally would be part of the source tree as well (scripts dir perhaps)

joguSD pushed a commit that referenced this issue Feb 19, 2019
This adds the missing pagination definitions for the CloudFormation APIs, as described in #1462.

I've tested DescribeChangeSet and ListChangeSets and both work as expected after this change,

```
client = boto3.client('cloudformation', region_name='eu-west-1')

paginator = client.get_paginator('list_change_sets')
page_iterator = paginator.paginate(StackName='MyStack')

for page in page_iterator:
    print(page)
```
@kristianperkins
Copy link

The script doesn't identify methods where the token is not named NextToken as can happen. For example cognito-idp uses the parameter NextToken for list_users_in_group, but uses PaginationToken for list_users. I'm not sure how many other services use different naming conventions for the name of the token used for pagination.

@JonathanDCohen
Copy link

Looks like this is still an issue:

client = boto3.client('cloudwatch', region_name='us-east-1')
paginator = client.get_paginator('get_metric_data')
Traceback (most recent call last):
...
    paginator = client.get_paginator('get_metric_data')
  File ".../env/lib/python3.6/site-packages/botocore/client.py", line 387, in get_paginator
    if not self.can_paginate(operation_name):
  File "/usr/local/google/home/cohenjon/Source/outline-electron-metrics/env/lib/python3.6/site-packages/botocore/client.py", line 420, in can_paginate
    actual_operation_name = self._PY_TO_OP_NAME[operation_name]
KeyError: 'get_metric_data'

@brandond
Copy link
Contributor

brandond commented Aug 13, 2019

@JonathanDCohen I suspect you're on an out-of-date version of boto3. Have you tried updating? I'm on a version from March and it works fine.

>>> import boto3
>>> client = boto3.client('cloudwatch')
>>> client.get_paginator('get_metric_data')
<botocore.client.CloudWatch.Paginator.GetMetricData object at 0x7f7e9e3bdfd0>
>>> boto3.__version__
'1.9.122'

@JonathanDCohen
Copy link

@brandond yeah that was it. All figured out :)

@dacut
Copy link

dacut commented Dec 20, 2019

The kinesis.list_shards paginator has issues; the API interface is problematic in that it wants StreamName to be set on the first call, but not set when NextToken is passed. (ugh.)

Python 3.7.5 (default, Nov  1 2019, 02:16:23)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.10.2 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import boto3.session

In [2]: boto3.__version__
Out[2]: '1.10.43'

In [3]: kinesis = boto3.session.Session(profile_name="xxxxxxxx").client("kinesis")

In [4]: paginator = kinesis.get_paginator("list_shards").paginate(StreamName="my-stream-name", PaginationConfig={"PageSize": 2})

In [5]: for page in paginator:
   ...:     print(page)
   ...:
{'Shards': [...], 'NextToken': '...', 'ResponseMetadata': {...}
---------------------------------------------------------------------------
InvalidArgumentException                  Traceback (most recent call last)
<ipython-input-5-d3d91b85e827> in <module>
----> 1 for page in paginator:
      2     print(page)
      3

~/projects/mars-ntr-load-test/venv/lib/python3.7/site-packages/botocore/paginate.py in __iter__(self)
    253         self._inject_starting_params(current_kwargs)
    254         while True:
--> 255             response = self._make_request(current_kwargs)
    256             parsed = self._extract_parsed_response(response)
    257             if first_request:

~/projects/mars-ntr-load-test/venv/lib/python3.7/site-packages/botocore/paginate.py in _make_request(self, current_kwargs)
    330
    331     def _make_request(self, current_kwargs):
--> 332         return self._method(**current_kwargs)
    333
    334     def _extract_parsed_response(self, response):

~/projects/mars-ntr-load-test/venv/lib/python3.7/site-packages/botocore/client.py in _api_call(self, *args, **kwargs)
    274                     "%s() only accepts keyword arguments." % py_operation_name)
    275             # The "self" in this scope is referring to the BaseClient.
--> 276             return self._make_api_call(operation_name, kwargs)
    277
    278         _api_call.__name__ = str(py_operation_name)

~/projects/mars-ntr-load-test/venv/lib/python3.7/site-packages/botocore/client.py in _make_api_call(self, operation_name, api_params)
    584             error_code = parsed_response.get("Error", {}).get("Code")
    585             error_class = self.exceptions.from_code(error_code)
--> 586             raise error_class(parsed_response, operation_name)
    587         else:
    588             return parsed_response

@PatMyron
Copy link

PatMyron commented Oct 11, 2020

The script doesn't identify methods where the token is not named NextToken as can happen. For example cognito-idp uses the parameter NextToken for list_users_in_group, but uses PaginationToken for list_users. I'm not sure how many other services use different naming conventions for the name of the token used for pagination.

@iann0036 investigated: https://github.com/iann0036/aws-pagination-rules

Chart: Distribution of AWS service count by pagination method

I also investigated: aws-cloudformation/cloudformation-cli#663


unmerged PRs: #1470, #1847, #2004, #2018, #2104, #2177

@khneal
Copy link

khneal commented Jan 14, 2021

I ran into a missing paginator for a function that uses "nextToken" instead of "NextToken"... it seems like this should have been fixed by now.

I have a script that generates paginators, constrained heavily to only generate those that I can be absolutely certain about. I just merged a PR stemming from that that added a ton. What we really need to do is to have that be part of our release automation. Right now we're relying pretty much entirely on getting them from upstream.

@JordonPhillips - would you be willing to share your script so others can use it?

CONTRIBUTING.rst mentions this topic first added here:

We may choose not to accept pull requests that change the JSON service descriptions...
We generate these files upstream based on our internal knowledge of the AWS services. If there is something incorrect with or missing from these files, it may be more appropriate to submit an issue so we can get the issue fixed upstream.

I see one-offs being added to the code, but there are also several PRs sitting open (see above). Are one-offs now allowed?

@jamesls - since you updated CONTRIBUTING.rst, where is the upstream location that we can modify to get this fixed across SDKs for all languages?

@RyanFitzSimmonsAK RyanFitzSimmonsAK added the p2 This is a standard priority issue label Nov 9, 2022
@tim-finnigan tim-finnigan self-assigned this Nov 22, 2022
@tim-finnigan
Copy link
Contributor

Service teams are now the owners of their paginator models as those model definitions are shared across AWS SDKs. We are currently tracking paginator requests here in our cross-SDK respository: https://github.com/aws/aws-sdk/issues?q=is%3Aissue+is%3Aopen+label%3Apaginator. If you'd like to see a paginator for a specific service/API, please create an issue in that repository with your use case and request.

You can also consider reaching out through AWS Support for further escalation on these types of requests. But since the paginator additions would need to happen upstream rather than in botocore directly, I'm going to close this issue. Please let us know if you had any questions or feedback regarding this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request This issue requests a feature. p2 This is a standard priority issue paginator
Projects
None yet
Development

No branches or pull requests