wxcli 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wxcli/__init__.py +4 -0
- wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
- wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
- wxcli/_playbook/.claude/rules/cleanup.md +29 -0
- wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
- wxcli/_playbook/.claude/rules/org-health.md +14 -0
- wxcli/_playbook/.claude/settings.json +8 -0
- wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
- wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
- wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
- wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
- wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
- wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
- wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
- wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
- wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
- wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
- wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
- wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
- wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
- wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
- wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
- wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
- wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
- wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
- wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
- wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
- wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
- wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
- wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
- wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
- wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
- wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
- wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
- wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
- wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
- wxcli/_playbook/CLAUDE.md +373 -0
- wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
- wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
- wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
- wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
- wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
- wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
- wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
- wxcli/_playbook/docs/reference/admin-partner.md +357 -0
- wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
- wxcli/_playbook/docs/reference/authentication.md +965 -0
- wxcli/_playbook/docs/reference/call-control.md +1205 -0
- wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
- wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
- wxcli/_playbook/docs/reference/call-routing.md +2304 -0
- wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
- wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
- wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
- wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
- wxcli/_playbook/docs/reference/devices-core.md +1869 -0
- wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
- wxcli/_playbook/docs/reference/devices-platform.md +467 -0
- wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
- wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
- wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
- wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
- wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
- wxcli/_playbook/docs/reference/meetings-content.md +473 -0
- wxcli/_playbook/docs/reference/meetings-core.md +903 -0
- wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
- wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
- wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
- wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
- wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
- wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
- wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
- wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
- wxcli/_playbook/docs/reference/provisioning.md +1366 -0
- wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
- wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
- wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
- wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
- wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
- wxcli/_version.py +24 -0
- wxcli/auth.py +137 -0
- wxcli/commands/__init__.py +0 -0
- wxcli/commands/_registry.py +181 -0
- wxcli/commands/activation_email.py +103 -0
- wxcli/commands/admin_recordings.py +585 -0
- wxcli/commands/analytics.py +105 -0
- wxcli/commands/announcement_playlists.py +219 -0
- wxcli/commands/announcements.py +519 -0
- wxcli/commands/archive_users.py +36 -0
- wxcli/commands/attachment_actions.py +60 -0
- wxcli/commands/audit_events.py +83 -0
- wxcli/commands/authorizations.py +113 -0
- wxcli/commands/auto_attendant.py +642 -0
- wxcli/commands/broadworks_billing_reports.py +126 -0
- wxcli/commands/broadworks_enterprises.py +160 -0
- wxcli/commands/broadworks_subscribers.py +319 -0
- wxcli/commands/broadworks_workspaces.py +108 -0
- wxcli/commands/call_controls.py +1304 -0
- wxcli/commands/call_park.py +494 -0
- wxcli/commands/call_pickup.py +229 -0
- wxcli/commands/call_queue.py +1878 -0
- wxcli/commands/call_recording.py +707 -0
- wxcli/commands/call_routing.py +1610 -0
- wxcli/commands/call_settings_for_me_phase_5.py +212 -0
- wxcli/commands/caller_reputation.py +169 -0
- wxcli/commands/calling_service.py +305 -0
- wxcli/commands/cc_address_book.py +770 -0
- wxcli/commands/cc_agent_greetings.py +242 -0
- wxcli/commands/cc_agent_summaries.py +39 -0
- wxcli/commands/cc_agent_wellbeing.py +216 -0
- wxcli/commands/cc_agents.py +425 -0
- wxcli/commands/cc_ai_assistant.py +55 -0
- wxcli/commands/cc_ai_feature.py +294 -0
- wxcli/commands/cc_audio_files.py +149 -0
- wxcli/commands/cc_auto_csat.py +311 -0
- wxcli/commands/cc_aux_code.py +458 -0
- wxcli/commands/cc_business_hour.py +353 -0
- wxcli/commands/cc_call_monitoring.py +228 -0
- wxcli/commands/cc_callbacks.py +194 -0
- wxcli/commands/cc_campaign.py +212 -0
- wxcli/commands/cc_captures.py +39 -0
- wxcli/commands/cc_contact_list.py +169 -0
- wxcli/commands/cc_contact_number.py +295 -0
- wxcli/commands/cc_data_sources.py +235 -0
- wxcli/commands/cc_desktop_layout.py +380 -0
- wxcli/commands/cc_desktop_profile.py +322 -0
- wxcli/commands/cc_dial_number.py +511 -0
- wxcli/commands/cc_dial_plan.py +347 -0
- wxcli/commands/cc_dnc.py +101 -0
- wxcli/commands/cc_entry_point.py +545 -0
- wxcli/commands/cc_ewt.py +51 -0
- wxcli/commands/cc_flow.py +477 -0
- wxcli/commands/cc_global_vars.py +430 -0
- wxcli/commands/cc_holiday_list.py +335 -0
- wxcli/commands/cc_journey.py +1261 -0
- wxcli/commands/cc_legacy_flows.py +49 -0
- wxcli/commands/cc_multimedia_profile.py +436 -0
- wxcli/commands/cc_notification.py +51 -0
- wxcli/commands/cc_outdial_ani.py +604 -0
- wxcli/commands/cc_overrides.py +341 -0
- wxcli/commands/cc_queue.py +1083 -0
- wxcli/commands/cc_queue_stats.py +55 -0
- wxcli/commands/cc_realtime.py +51 -0
- wxcli/commands/cc_resource_collection.py +312 -0
- wxcli/commands/cc_search.py +46 -0
- wxcli/commands/cc_site.py +400 -0
- wxcli/commands/cc_skill.py +350 -0
- wxcli/commands/cc_skill_profile.py +289 -0
- wxcli/commands/cc_subscriptions.py +426 -0
- wxcli/commands/cc_summaries.py +130 -0
- wxcli/commands/cc_tasks.py +844 -0
- wxcli/commands/cc_team.py +325 -0
- wxcli/commands/cc_user_profiles.py +349 -0
- wxcli/commands/cc_users.py +701 -0
- wxcli/commands/cc_work_types.py +363 -0
- wxcli/commands/cdr.py +89 -0
- wxcli/commands/classifications.py +38 -0
- wxcli/commands/cleanup.py +1427 -0
- wxcli/commands/client_settings.py +72 -0
- wxcli/commands/conference.py +328 -0
- wxcli/commands/configure.py +72 -0
- wxcli/commands/converged_recordings.py +347 -0
- wxcli/commands/converged_recordings_export.py +310 -0
- wxcli/commands/cq_playlists.py +42 -0
- wxcli/commands/cucm.py +2794 -0
- wxcli/commands/cucm_config.py +129 -0
- wxcli/commands/customer_assist.py +373 -0
- wxcli/commands/data_sources.py +227 -0
- wxcli/commands/dect_devices.py +787 -0
- wxcli/commands/device_configurations.py +77 -0
- wxcli/commands/device_dynamic_settings.py +320 -0
- wxcli/commands/device_settings.py +1489 -0
- wxcli/commands/devices.py +280 -0
- wxcli/commands/domains.py +142 -0
- wxcli/commands/ecm.py +178 -0
- wxcli/commands/emergency_services.py +827 -0
- wxcli/commands/events.py +83 -0
- wxcli/commands/external_voicemail.py +52 -0
- wxcli/commands/groups.py +206 -0
- wxcli/commands/guest_management.py +76 -0
- wxcli/commands/hds.py +340 -0
- wxcli/commands/hot_desk.py +67 -0
- wxcli/commands/hot_desking_members.py +118 -0
- wxcli/commands/hot_desking_portal.py +124 -0
- wxcli/commands/hunt_group.py +577 -0
- wxcli/commands/hybrid_clusters.py +71 -0
- wxcli/commands/hybrid_connectors.py +67 -0
- wxcli/commands/identity_org.py +159 -0
- wxcli/commands/init_playbook.py +155 -0
- wxcli/commands/licenses.py +106 -0
- wxcli/commands/live_monitoring.py +40 -0
- wxcli/commands/location_call_handling.py +577 -0
- wxcli/commands/location_schedules.py +341 -0
- wxcli/commands/location_settings.py +1297 -0
- wxcli/commands/location_voicemail.py +494 -0
- wxcli/commands/locations.py +336 -0
- wxcli/commands/meeting_captions.py +110 -0
- wxcli/commands/meeting_chats.py +63 -0
- wxcli/commands/meeting_invitees.py +234 -0
- wxcli/commands/meeting_messages.py +28 -0
- wxcli/commands/meeting_participants.py +278 -0
- wxcli/commands/meeting_polls.py +111 -0
- wxcli/commands/meeting_preferences.py +515 -0
- wxcli/commands/meeting_qa.py +78 -0
- wxcli/commands/meeting_qualities.py +43 -0
- wxcli/commands/meeting_reports.py +101 -0
- wxcli/commands/meeting_session_types.py +105 -0
- wxcli/commands/meeting_site.py +57 -0
- wxcli/commands/meeting_slido.py +44 -0
- wxcli/commands/meeting_summaries.py +92 -0
- wxcli/commands/meeting_tracking_codes.py +233 -0
- wxcli/commands/meeting_transcripts.py +230 -0
- wxcli/commands/meetings.py +1997 -0
- wxcli/commands/memberships.py +164 -0
- wxcli/commands/messages.py +213 -0
- wxcli/commands/mode_management.py +244 -0
- wxcli/commands/my_call_settings.py +3577 -0
- wxcli/commands/numbers.py +405 -0
- wxcli/commands/operating_modes.py +410 -0
- wxcli/commands/org_contacts.py +284 -0
- wxcli/commands/org_health_cli.py +55 -0
- wxcli/commands/org_settings.py +71 -0
- wxcli/commands/organizations.py +83 -0
- wxcli/commands/paging_group.py +257 -0
- wxcli/commands/partner_admins.py +141 -0
- wxcli/commands/partner_reports.py +188 -0
- wxcli/commands/partner_tags.py +216 -0
- wxcli/commands/people.py +279 -0
- wxcli/commands/person_call_settings.py +71 -0
- wxcli/commands/pstn.py +280 -0
- wxcli/commands/recording_report.py +154 -0
- wxcli/commands/report_templates.py +38 -0
- wxcli/commands/reports.py +144 -0
- wxcli/commands/resource_group_memberships.py +160 -0
- wxcli/commands/resource_groups.py +67 -0
- wxcli/commands/roles.py +63 -0
- wxcli/commands/room_tabs.py +160 -0
- wxcli/commands/rooms.py +225 -0
- wxcli/commands/scim_bulk.py +46 -0
- wxcli/commands/scim_groups.py +246 -0
- wxcli/commands/scim_schemas.py +82 -0
- wxcli/commands/scim_users.py +283 -0
- wxcli/commands/security_audit.py +54 -0
- wxcli/commands/service_apps.py +51 -0
- wxcli/commands/single_number_reach.py +209 -0
- wxcli/commands/team_memberships.py +155 -0
- wxcli/commands/teams.py +153 -0
- wxcli/commands/ucm_profile.py +42 -0
- wxcli/commands/update.py +219 -0
- wxcli/commands/user_settings.py +5116 -0
- wxcli/commands/video_mesh.py +1090 -0
- wxcli/commands/virtual_extensions.py +502 -0
- wxcli/commands/virtual_line_settings.py +2072 -0
- wxcli/commands/webhooks.py +176 -0
- wxcli/commands/wholesale_billing_reports.py +147 -0
- wxcli/commands/wholesale_provisioning.py +523 -0
- wxcli/commands/workspace_locations.py +339 -0
- wxcli/commands/workspace_metrics.py +103 -0
- wxcli/commands/workspace_personalization.py +70 -0
- wxcli/commands/workspace_settings.py +3347 -0
- wxcli/commands/workspaces.py +279 -0
- wxcli/commands/xapi.py +114 -0
- wxcli/config.py +139 -0
- wxcli/errors.py +77 -0
- wxcli/main.py +210 -0
- wxcli/migration/CLAUDE.md +106 -0
- wxcli/migration/__init__.py +1 -0
- wxcli/migration/advisory/CLAUDE.md +196 -0
- wxcli/migration/advisory/__init__.py +46 -0
- wxcli/migration/advisory/advisor.py +107 -0
- wxcli/migration/advisory/advisory_patterns.py +2552 -0
- wxcli/migration/advisory/recommendation_rules.py +835 -0
- wxcli/migration/cucm/CLAUDE.md +74 -0
- wxcli/migration/cucm/__init__.py +5 -0
- wxcli/migration/cucm/connection.py +265 -0
- wxcli/migration/cucm/discovery.py +225 -0
- wxcli/migration/cucm/extractors/__init__.py +1 -0
- wxcli/migration/cucm/extractors/announcements.py +92 -0
- wxcli/migration/cucm/extractors/base.py +90 -0
- wxcli/migration/cucm/extractors/device_profiles.py +98 -0
- wxcli/migration/cucm/extractors/devices.py +193 -0
- wxcli/migration/cucm/extractors/e911.py +103 -0
- wxcli/migration/cucm/extractors/features.py +309 -0
- wxcli/migration/cucm/extractors/helpers.py +73 -0
- wxcli/migration/cucm/extractors/informational.py +295 -0
- wxcli/migration/cucm/extractors/locations.py +221 -0
- wxcli/migration/cucm/extractors/moh.py +100 -0
- wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
- wxcli/migration/cucm/extractors/routing.py +493 -0
- wxcli/migration/cucm/extractors/shared_lines.py +146 -0
- wxcli/migration/cucm/extractors/templates.py +229 -0
- wxcli/migration/cucm/extractors/tier4.py +173 -0
- wxcli/migration/cucm/extractors/users.py +240 -0
- wxcli/migration/cucm/extractors/voicemail.py +243 -0
- wxcli/migration/cucm/extractors/workspaces.py +88 -0
- wxcli/migration/cucm/unity_connection.py +304 -0
- wxcli/migration/execute/CLAUDE.md +372 -0
- wxcli/migration/execute/__init__.py +303 -0
- wxcli/migration/execute/batch.py +277 -0
- wxcli/migration/execute/dependency.py +483 -0
- wxcli/migration/execute/engine.py +964 -0
- wxcli/migration/execute/handlers.py +2232 -0
- wxcli/migration/execute/planner.py +1939 -0
- wxcli/migration/execute/runtime.py +571 -0
- wxcli/migration/export/CLAUDE.md +49 -0
- wxcli/migration/export/__init__.py +8 -0
- wxcli/migration/export/csv_export.py +126 -0
- wxcli/migration/export/deployment_plan.py +479 -0
- wxcli/migration/export/json_export.py +60 -0
- wxcli/migration/models.py +941 -0
- wxcli/migration/phone_models.py +50 -0
- wxcli/migration/preflight/CLAUDE.md +52 -0
- wxcli/migration/preflight/__init__.py +89 -0
- wxcli/migration/preflight/checks.py +911 -0
- wxcli/migration/preflight/runner.py +293 -0
- wxcli/migration/rate_limiter.py +144 -0
- wxcli/migration/report/CLAUDE.md +245 -0
- wxcli/migration/report/__init__.py +7 -0
- wxcli/migration/report/appendix.py +2437 -0
- wxcli/migration/report/assembler.py +183 -0
- wxcli/migration/report/charts.py +263 -0
- wxcli/migration/report/executive.py +776 -0
- wxcli/migration/report/explainer.py +704 -0
- wxcli/migration/report/helpers.py +74 -0
- wxcli/migration/report/ingest.py +152 -0
- wxcli/migration/report/notice_templates.py +192 -0
- wxcli/migration/report/score.py +375 -0
- wxcli/migration/report/styles.py +1052 -0
- wxcli/migration/report/user_diff.py +1052 -0
- wxcli/migration/report/user_notice.py +425 -0
- wxcli/migration/state.py +139 -0
- wxcli/migration/store.py +860 -0
- wxcli/migration/transform/CLAUDE.md +107 -0
- wxcli/migration/transform/__init__.py +12 -0
- wxcli/migration/transform/analysis_pipeline.py +453 -0
- wxcli/migration/transform/analyzers/__init__.py +142 -0
- wxcli/migration/transform/analyzers/css_permission.py +189 -0
- wxcli/migration/transform/analyzers/css_routing.py +335 -0
- wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
- wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
- wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
- wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
- wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
- wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
- wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
- wxcli/migration/transform/analyzers/missing_data.py +300 -0
- wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
- wxcli/migration/transform/analyzers/shared_line.py +170 -0
- wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
- wxcli/migration/transform/analyzers/workspace_license.py +212 -0
- wxcli/migration/transform/cross_reference.py +1136 -0
- wxcli/migration/transform/cucm_pattern.py +246 -0
- wxcli/migration/transform/decisions.py +301 -0
- wxcli/migration/transform/e164.py +145 -0
- wxcli/migration/transform/engine.py +256 -0
- wxcli/migration/transform/mappers/CLAUDE.md +123 -0
- wxcli/migration/transform/mappers/__init__.py +76 -0
- wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
- wxcli/migration/transform/mappers/base.py +190 -0
- wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
- wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
- wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
- wxcli/migration/transform/mappers/css_mapper.py +868 -0
- wxcli/migration/transform/mappers/dect_mapper.py +367 -0
- wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
- wxcli/migration/transform/mappers/device_mapper.py +227 -0
- wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
- wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
- wxcli/migration/transform/mappers/e911_mapper.py +129 -0
- wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
- wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
- wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
- wxcli/migration/transform/mappers/line_mapper.py +310 -0
- wxcli/migration/transform/mappers/location_mapper.py +235 -0
- wxcli/migration/transform/mappers/moh_mapper.py +114 -0
- wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
- wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
- wxcli/migration/transform/mappers/routing_mapper.py +821 -0
- wxcli/migration/transform/mappers/snr_mapper.py +201 -0
- wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
- wxcli/migration/transform/mappers/user_mapper.py +264 -0
- wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
- wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
- wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
- wxcli/migration/transform/normalizers.py +2008 -0
- wxcli/migration/transform/pattern_converter.py +106 -0
- wxcli/migration/transform/pipeline.py +271 -0
- wxcli/migration/transform/rules.py +255 -0
- wxcli/org_health/CLAUDE.md +63 -0
- wxcli/org_health/__init__.py +7 -0
- wxcli/org_health/analyze.py +93 -0
- wxcli/org_health/checks.py +458 -0
- wxcli/org_health/collector.py +62 -0
- wxcli/org_health/models.py +78 -0
- wxcli/org_health/report.py +300 -0
- wxcli/output.py +101 -0
- wxcli-1.2.0.dist-info/METADATA +505 -0
- wxcli-1.2.0.dist-info/RECORD +413 -0
- wxcli-1.2.0.dist-info/WHEEL +5 -0
- wxcli-1.2.0.dist-info/entry_points.txt +2 -0
- wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
- wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
- wxcli-1.2.0.dist-info/scm_version.json +8 -0
- wxcli-1.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1090 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import get_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling video-mesh.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
15
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
16
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
17
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
18
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
19
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
20
|
+
):
|
|
21
|
+
"""List Clusters Availability."""
|
|
22
|
+
api = get_api(debug=debug)
|
|
23
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters/availability"
|
|
24
|
+
params = {}
|
|
25
|
+
if from_param is not None:
|
|
26
|
+
params["from"] = from_param
|
|
27
|
+
if to is not None:
|
|
28
|
+
params["to"] = to
|
|
29
|
+
if limit > 0:
|
|
30
|
+
params["max"] = limit
|
|
31
|
+
if offset > 0:
|
|
32
|
+
params["start"] = offset
|
|
33
|
+
org_id = get_org_id()
|
|
34
|
+
if org_id is not None:
|
|
35
|
+
params["orgId"] = org_id
|
|
36
|
+
result = None
|
|
37
|
+
try:
|
|
38
|
+
result = api.session.rest_get(url, params=params)
|
|
39
|
+
except WebexError as e:
|
|
40
|
+
handle_rest_error(e)
|
|
41
|
+
result = result or []
|
|
42
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
43
|
+
if output == "json":
|
|
44
|
+
print_json(items)
|
|
45
|
+
else:
|
|
46
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.command("show")
|
|
51
|
+
def show(
|
|
52
|
+
cluster_id: str = typer.Argument(help="clusterId"),
|
|
53
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
54
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
55
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
56
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
57
|
+
):
|
|
58
|
+
"""Get Cluster Availability."""
|
|
59
|
+
api = get_api(debug=debug)
|
|
60
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters/availability/{cluster_id}"
|
|
61
|
+
params = {}
|
|
62
|
+
if from_param is not None:
|
|
63
|
+
params["from"] = from_param
|
|
64
|
+
if to is not None:
|
|
65
|
+
params["to"] = to
|
|
66
|
+
try:
|
|
67
|
+
result = api.session.rest_get(url, params=params)
|
|
68
|
+
except WebexError as e:
|
|
69
|
+
handle_rest_error(e)
|
|
70
|
+
if output == "json":
|
|
71
|
+
print_json(result)
|
|
72
|
+
else:
|
|
73
|
+
if isinstance(result, dict):
|
|
74
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
75
|
+
elif isinstance(result, list):
|
|
76
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
77
|
+
else:
|
|
78
|
+
print_json(result)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@app.command("list-availability")
|
|
83
|
+
def list_availability(
|
|
84
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
85
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
86
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="The unique Video Mesh cluster ID."),
|
|
87
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
88
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
89
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
90
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
91
|
+
):
|
|
92
|
+
"""List Node Availability."""
|
|
93
|
+
api = get_api(debug=debug)
|
|
94
|
+
url = f"https://webexapis.com/v1/videoMesh/nodes/availability"
|
|
95
|
+
params = {}
|
|
96
|
+
if from_param is not None:
|
|
97
|
+
params["from"] = from_param
|
|
98
|
+
if to is not None:
|
|
99
|
+
params["to"] = to
|
|
100
|
+
if cluster_id is not None:
|
|
101
|
+
params["clusterId"] = cluster_id
|
|
102
|
+
if limit > 0:
|
|
103
|
+
params["max"] = limit
|
|
104
|
+
if offset > 0:
|
|
105
|
+
params["start"] = offset
|
|
106
|
+
result = None
|
|
107
|
+
try:
|
|
108
|
+
result = api.session.rest_get(url, params=params)
|
|
109
|
+
except WebexError as e:
|
|
110
|
+
handle_rest_error(e)
|
|
111
|
+
result = result or []
|
|
112
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
113
|
+
if output == "json":
|
|
114
|
+
print_json(items)
|
|
115
|
+
else:
|
|
116
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@app.command("show-availability")
|
|
121
|
+
def show_availability(
|
|
122
|
+
node_id: str = typer.Argument(help="nodeId"),
|
|
123
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
124
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
125
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
126
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
127
|
+
):
|
|
128
|
+
"""Get Node Availability."""
|
|
129
|
+
api = get_api(debug=debug)
|
|
130
|
+
url = f"https://webexapis.com/v1/videoMesh/nodes/availability/{node_id}"
|
|
131
|
+
params = {}
|
|
132
|
+
if from_param is not None:
|
|
133
|
+
params["from"] = from_param
|
|
134
|
+
if to is not None:
|
|
135
|
+
params["to"] = to
|
|
136
|
+
try:
|
|
137
|
+
result = api.session.rest_get(url, params=params)
|
|
138
|
+
except WebexError as e:
|
|
139
|
+
handle_rest_error(e)
|
|
140
|
+
if output == "json":
|
|
141
|
+
print_json(result)
|
|
142
|
+
else:
|
|
143
|
+
if isinstance(result, dict):
|
|
144
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
145
|
+
elif isinstance(result, list):
|
|
146
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
147
|
+
else:
|
|
148
|
+
print_json(result)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@app.command("list-media-health-monitor-test")
|
|
153
|
+
def list_media_health_monitor_test(
|
|
154
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
155
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
156
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
157
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
158
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
159
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
160
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
161
|
+
):
|
|
162
|
+
"""List Media Health Monitoring Tool Test results V2."""
|
|
163
|
+
api = get_api(debug=debug)
|
|
164
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/mediaHealthMonitorTest"
|
|
165
|
+
params = {}
|
|
166
|
+
if trigger_type is not None:
|
|
167
|
+
params["triggerType"] = trigger_type
|
|
168
|
+
if from_param is not None:
|
|
169
|
+
params["from"] = from_param
|
|
170
|
+
if to is not None:
|
|
171
|
+
params["to"] = to
|
|
172
|
+
if limit > 0:
|
|
173
|
+
params["max"] = limit
|
|
174
|
+
if offset > 0:
|
|
175
|
+
params["start"] = offset
|
|
176
|
+
org_id = get_org_id()
|
|
177
|
+
if org_id is not None:
|
|
178
|
+
params["orgId"] = org_id
|
|
179
|
+
result = None
|
|
180
|
+
try:
|
|
181
|
+
result = api.session.rest_get(url, params=params)
|
|
182
|
+
except WebexError as e:
|
|
183
|
+
handle_rest_error(e)
|
|
184
|
+
result = result or []
|
|
185
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
186
|
+
if output == "json":
|
|
187
|
+
print_json(items)
|
|
188
|
+
else:
|
|
189
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@app.command("list-clusters-media-health-monitor-test")
|
|
194
|
+
def list_clusters_media_health_monitor_test(
|
|
195
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="Unique ID of the Video Mesh cluster."),
|
|
196
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
197
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
198
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
199
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
200
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
201
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
202
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
203
|
+
):
|
|
204
|
+
"""Get Media Health Monitoring Tool Test results for clusters V2."""
|
|
205
|
+
api = get_api(debug=debug)
|
|
206
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/mediaHealthMonitorTest/clusters"
|
|
207
|
+
params = {}
|
|
208
|
+
if cluster_id is not None:
|
|
209
|
+
params["clusterId"] = cluster_id
|
|
210
|
+
if trigger_type is not None:
|
|
211
|
+
params["triggerType"] = trigger_type
|
|
212
|
+
if from_param is not None:
|
|
213
|
+
params["from"] = from_param
|
|
214
|
+
if to is not None:
|
|
215
|
+
params["to"] = to
|
|
216
|
+
if limit > 0:
|
|
217
|
+
params["max"] = limit
|
|
218
|
+
if offset > 0:
|
|
219
|
+
params["start"] = offset
|
|
220
|
+
result = None
|
|
221
|
+
try:
|
|
222
|
+
result = api.session.rest_get(url, params=params)
|
|
223
|
+
except WebexError as e:
|
|
224
|
+
handle_rest_error(e)
|
|
225
|
+
result = result or []
|
|
226
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
227
|
+
if output == "json":
|
|
228
|
+
print_json(items)
|
|
229
|
+
else:
|
|
230
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
@app.command("list-nodes-media-health-monitor-test")
|
|
235
|
+
def list_nodes_media_health_monitor_test(
|
|
236
|
+
node_id: str = typer.Option(..., "--node-id", help="Unique ID of the Video Mesh node."),
|
|
237
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
238
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
239
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
240
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
241
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
242
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
243
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
244
|
+
):
|
|
245
|
+
"""Get Media Health Monitoring Tool Test results for node V2."""
|
|
246
|
+
api = get_api(debug=debug)
|
|
247
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/mediaHealthMonitorTest/nodes"
|
|
248
|
+
params = {}
|
|
249
|
+
if node_id is not None:
|
|
250
|
+
params["nodeId"] = node_id
|
|
251
|
+
if trigger_type is not None:
|
|
252
|
+
params["triggerType"] = trigger_type
|
|
253
|
+
if from_param is not None:
|
|
254
|
+
params["from"] = from_param
|
|
255
|
+
if to is not None:
|
|
256
|
+
params["to"] = to
|
|
257
|
+
if limit > 0:
|
|
258
|
+
params["max"] = limit
|
|
259
|
+
if offset > 0:
|
|
260
|
+
params["start"] = offset
|
|
261
|
+
result = None
|
|
262
|
+
try:
|
|
263
|
+
result = api.session.rest_get(url, params=params)
|
|
264
|
+
except WebexError as e:
|
|
265
|
+
handle_rest_error(e)
|
|
266
|
+
result = result or []
|
|
267
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
268
|
+
if output == "json":
|
|
269
|
+
print_json(items)
|
|
270
|
+
else:
|
|
271
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@app.command("list-cloud-overflow")
|
|
276
|
+
def list_cloud_overflow(
|
|
277
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
278
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
279
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
280
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
281
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
282
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
283
|
+
):
|
|
284
|
+
"""List Overflow to Cloud details."""
|
|
285
|
+
api = get_api(debug=debug)
|
|
286
|
+
url = f"https://webexapis.com/v1/videoMesh/cloudOverflow"
|
|
287
|
+
params = {}
|
|
288
|
+
if from_param is not None:
|
|
289
|
+
params["from"] = from_param
|
|
290
|
+
if to is not None:
|
|
291
|
+
params["to"] = to
|
|
292
|
+
if limit > 0:
|
|
293
|
+
params["max"] = limit
|
|
294
|
+
if offset > 0:
|
|
295
|
+
params["start"] = offset
|
|
296
|
+
org_id = get_org_id()
|
|
297
|
+
if org_id is not None:
|
|
298
|
+
params["orgId"] = org_id
|
|
299
|
+
result = None
|
|
300
|
+
try:
|
|
301
|
+
result = api.session.rest_get(url, params=params)
|
|
302
|
+
except WebexError as e:
|
|
303
|
+
handle_rest_error(e)
|
|
304
|
+
result = result or []
|
|
305
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
306
|
+
if output == "json":
|
|
307
|
+
print_json(items)
|
|
308
|
+
else:
|
|
309
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@app.command("list-call-redirects-video-mesh")
|
|
314
|
+
def list_call_redirects_video_mesh(
|
|
315
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
316
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
317
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
318
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
319
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
320
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
321
|
+
):
|
|
322
|
+
"""List Cluster Redirect details."""
|
|
323
|
+
api = get_api(debug=debug)
|
|
324
|
+
url = f"https://webexapis.com/v1/videoMesh/callRedirects"
|
|
325
|
+
params = {}
|
|
326
|
+
if from_param is not None:
|
|
327
|
+
params["from"] = from_param
|
|
328
|
+
if to is not None:
|
|
329
|
+
params["to"] = to
|
|
330
|
+
if limit > 0:
|
|
331
|
+
params["max"] = limit
|
|
332
|
+
if offset > 0:
|
|
333
|
+
params["start"] = offset
|
|
334
|
+
org_id = get_org_id()
|
|
335
|
+
if org_id is not None:
|
|
336
|
+
params["orgId"] = org_id
|
|
337
|
+
result = None
|
|
338
|
+
try:
|
|
339
|
+
result = api.session.rest_get(url, params=params)
|
|
340
|
+
except WebexError as e:
|
|
341
|
+
handle_rest_error(e)
|
|
342
|
+
result = result or []
|
|
343
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
344
|
+
if output == "json":
|
|
345
|
+
print_json(items)
|
|
346
|
+
else:
|
|
347
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@app.command("list-call-redirects-clusters")
|
|
352
|
+
def list_call_redirects_clusters(
|
|
353
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
354
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
355
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="The unique Video Mesh Cluster ID."),
|
|
356
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
357
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
358
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
359
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
360
|
+
):
|
|
361
|
+
"""Get Cluster Redirect details."""
|
|
362
|
+
api = get_api(debug=debug)
|
|
363
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters/callRedirects"
|
|
364
|
+
params = {}
|
|
365
|
+
if from_param is not None:
|
|
366
|
+
params["from"] = from_param
|
|
367
|
+
if to is not None:
|
|
368
|
+
params["to"] = to
|
|
369
|
+
if cluster_id is not None:
|
|
370
|
+
params["clusterId"] = cluster_id
|
|
371
|
+
if limit > 0:
|
|
372
|
+
params["max"] = limit
|
|
373
|
+
if offset > 0:
|
|
374
|
+
params["start"] = offset
|
|
375
|
+
result = None
|
|
376
|
+
try:
|
|
377
|
+
result = api.session.rest_get(url, params=params)
|
|
378
|
+
except WebexError as e:
|
|
379
|
+
handle_rest_error(e)
|
|
380
|
+
result = result or []
|
|
381
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
382
|
+
if output == "json":
|
|
383
|
+
print_json(items)
|
|
384
|
+
else:
|
|
385
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@app.command("list-utilization-video-mesh")
|
|
390
|
+
def list_utilization_video_mesh(
|
|
391
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
392
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
393
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
394
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
395
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
396
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
397
|
+
):
|
|
398
|
+
"""List Clusters Utilization."""
|
|
399
|
+
api = get_api(debug=debug)
|
|
400
|
+
url = f"https://webexapis.com/v1/videoMesh/utilization"
|
|
401
|
+
params = {}
|
|
402
|
+
if from_param is not None:
|
|
403
|
+
params["from"] = from_param
|
|
404
|
+
if to is not None:
|
|
405
|
+
params["to"] = to
|
|
406
|
+
if limit > 0:
|
|
407
|
+
params["max"] = limit
|
|
408
|
+
if offset > 0:
|
|
409
|
+
params["start"] = offset
|
|
410
|
+
org_id = get_org_id()
|
|
411
|
+
if org_id is not None:
|
|
412
|
+
params["orgId"] = org_id
|
|
413
|
+
result = None
|
|
414
|
+
try:
|
|
415
|
+
result = api.session.rest_get(url, params=params)
|
|
416
|
+
except WebexError as e:
|
|
417
|
+
handle_rest_error(e)
|
|
418
|
+
result = result or []
|
|
419
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
420
|
+
if output == "json":
|
|
421
|
+
print_json(items)
|
|
422
|
+
else:
|
|
423
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@app.command("list-utilization-clusters")
|
|
428
|
+
def list_utilization_clusters(
|
|
429
|
+
from_param: str = typer.Option(..., "--from", help="The starting date and time of the requested data in any [ISO"),
|
|
430
|
+
to: str = typer.Option(..., "--to", help="The ending date and time of the requested data in any [ISO 8"),
|
|
431
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="The unique Video Mesh Cluster ID."),
|
|
432
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
433
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
434
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
435
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
436
|
+
):
|
|
437
|
+
"""Get Cluster Utilization details."""
|
|
438
|
+
api = get_api(debug=debug)
|
|
439
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters/utilization"
|
|
440
|
+
params = {}
|
|
441
|
+
if from_param is not None:
|
|
442
|
+
params["from"] = from_param
|
|
443
|
+
if to is not None:
|
|
444
|
+
params["to"] = to
|
|
445
|
+
if cluster_id is not None:
|
|
446
|
+
params["clusterId"] = cluster_id
|
|
447
|
+
if limit > 0:
|
|
448
|
+
params["max"] = limit
|
|
449
|
+
if offset > 0:
|
|
450
|
+
params["start"] = offset
|
|
451
|
+
result = None
|
|
452
|
+
try:
|
|
453
|
+
result = api.session.rest_get(url, params=params)
|
|
454
|
+
except WebexError as e:
|
|
455
|
+
handle_rest_error(e)
|
|
456
|
+
result = result or []
|
|
457
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
458
|
+
if output == "json":
|
|
459
|
+
print_json(items)
|
|
460
|
+
else:
|
|
461
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
@app.command("list-reachability-test")
|
|
466
|
+
def list_reachability_test(
|
|
467
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
468
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
469
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
470
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
471
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
472
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
473
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
474
|
+
):
|
|
475
|
+
"""List Reachability Test results V2."""
|
|
476
|
+
api = get_api(debug=debug)
|
|
477
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/reachabilityTest"
|
|
478
|
+
params = {}
|
|
479
|
+
if trigger_type is not None:
|
|
480
|
+
params["triggerType"] = trigger_type
|
|
481
|
+
if from_param is not None:
|
|
482
|
+
params["from"] = from_param
|
|
483
|
+
if to is not None:
|
|
484
|
+
params["to"] = to
|
|
485
|
+
if limit > 0:
|
|
486
|
+
params["max"] = limit
|
|
487
|
+
if offset > 0:
|
|
488
|
+
params["start"] = offset
|
|
489
|
+
org_id = get_org_id()
|
|
490
|
+
if org_id is not None:
|
|
491
|
+
params["orgId"] = org_id
|
|
492
|
+
result = None
|
|
493
|
+
try:
|
|
494
|
+
result = api.session.rest_get(url, params=params)
|
|
495
|
+
except WebexError as e:
|
|
496
|
+
handle_rest_error(e)
|
|
497
|
+
result = result or []
|
|
498
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
499
|
+
if output == "json":
|
|
500
|
+
print_json(items)
|
|
501
|
+
else:
|
|
502
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@app.command("list-clusters-reachability-test")
|
|
507
|
+
def list_clusters_reachability_test(
|
|
508
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="Unique ID of the Video Mesh cluster."),
|
|
509
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
510
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
511
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
512
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
513
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
514
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
515
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
516
|
+
):
|
|
517
|
+
"""Get Reachability Test results for cluster V2."""
|
|
518
|
+
api = get_api(debug=debug)
|
|
519
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/reachabilityTest/clusters"
|
|
520
|
+
params = {}
|
|
521
|
+
if cluster_id is not None:
|
|
522
|
+
params["clusterId"] = cluster_id
|
|
523
|
+
if trigger_type is not None:
|
|
524
|
+
params["triggerType"] = trigger_type
|
|
525
|
+
if from_param is not None:
|
|
526
|
+
params["from"] = from_param
|
|
527
|
+
if to is not None:
|
|
528
|
+
params["to"] = to
|
|
529
|
+
if limit > 0:
|
|
530
|
+
params["max"] = limit
|
|
531
|
+
if offset > 0:
|
|
532
|
+
params["start"] = offset
|
|
533
|
+
result = None
|
|
534
|
+
try:
|
|
535
|
+
result = api.session.rest_get(url, params=params)
|
|
536
|
+
except WebexError as e:
|
|
537
|
+
handle_rest_error(e)
|
|
538
|
+
result = result or []
|
|
539
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
540
|
+
if output == "json":
|
|
541
|
+
print_json(items)
|
|
542
|
+
else:
|
|
543
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
@app.command("list-nodes-reachability-test")
|
|
548
|
+
def list_nodes_reachability_test(
|
|
549
|
+
node_id: str = typer.Option(..., "--node-id", help="Unique ID of the Video Mesh node."),
|
|
550
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
551
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
552
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
553
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
554
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
555
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
556
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
557
|
+
):
|
|
558
|
+
"""Get Reachability Test results for node V2."""
|
|
559
|
+
api = get_api(debug=debug)
|
|
560
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/reachabilityTest/nodes"
|
|
561
|
+
params = {}
|
|
562
|
+
if node_id is not None:
|
|
563
|
+
params["nodeId"] = node_id
|
|
564
|
+
if trigger_type is not None:
|
|
565
|
+
params["triggerType"] = trigger_type
|
|
566
|
+
if from_param is not None:
|
|
567
|
+
params["from"] = from_param
|
|
568
|
+
if to is not None:
|
|
569
|
+
params["to"] = to
|
|
570
|
+
if limit > 0:
|
|
571
|
+
params["max"] = limit
|
|
572
|
+
if offset > 0:
|
|
573
|
+
params["start"] = offset
|
|
574
|
+
result = None
|
|
575
|
+
try:
|
|
576
|
+
result = api.session.rest_get(url, params=params)
|
|
577
|
+
except WebexError as e:
|
|
578
|
+
handle_rest_error(e)
|
|
579
|
+
result = result or []
|
|
580
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
581
|
+
if output == "json":
|
|
582
|
+
print_json(items)
|
|
583
|
+
else:
|
|
584
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
@app.command("list-clusters-video-mesh")
|
|
589
|
+
def list_clusters_video_mesh(
|
|
590
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
591
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
592
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
593
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
594
|
+
):
|
|
595
|
+
"""List Cluster Details."""
|
|
596
|
+
api = get_api(debug=debug)
|
|
597
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters"
|
|
598
|
+
params = {}
|
|
599
|
+
if limit > 0:
|
|
600
|
+
params["max"] = limit
|
|
601
|
+
if offset > 0:
|
|
602
|
+
params["start"] = offset
|
|
603
|
+
org_id = get_org_id()
|
|
604
|
+
if org_id is not None:
|
|
605
|
+
params["orgId"] = org_id
|
|
606
|
+
result = None
|
|
607
|
+
try:
|
|
608
|
+
result = api.session.rest_get(url, params=params)
|
|
609
|
+
except WebexError as e:
|
|
610
|
+
handle_rest_error(e)
|
|
611
|
+
result = result or []
|
|
612
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
613
|
+
if output == "json":
|
|
614
|
+
print_json(items)
|
|
615
|
+
else:
|
|
616
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
@app.command("show-clusters")
|
|
621
|
+
def show_clusters(
|
|
622
|
+
cluster_id: str = typer.Argument(help="clusterId"),
|
|
623
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
624
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
625
|
+
):
|
|
626
|
+
"""Get Cluster Details."""
|
|
627
|
+
api = get_api(debug=debug)
|
|
628
|
+
url = f"https://webexapis.com/v1/videoMesh/clusters/{cluster_id}"
|
|
629
|
+
try:
|
|
630
|
+
result = api.session.rest_get(url)
|
|
631
|
+
except WebexError as e:
|
|
632
|
+
handle_rest_error(e)
|
|
633
|
+
if output == "json":
|
|
634
|
+
print_json(result)
|
|
635
|
+
else:
|
|
636
|
+
if isinstance(result, dict):
|
|
637
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
638
|
+
elif isinstance(result, list):
|
|
639
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
640
|
+
else:
|
|
641
|
+
print_json(result)
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
@app.command("create")
|
|
646
|
+
def create(
|
|
647
|
+
cluster_id: str = typer.Argument(help="clusterId"),
|
|
648
|
+
type_param: str = typer.Option(None, "--type", help="Choices: ReachabilityTest, NetworkTest, MediaHealthMonitorTest"),
|
|
649
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
650
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
651
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
652
|
+
):
|
|
653
|
+
"""Trigger on-demand test for cluster\n\nExample --json-body:\n '{"type":"ReachabilityTest","nodes":["..."]}'."""
|
|
654
|
+
api = get_api(debug=debug)
|
|
655
|
+
url = f"https://webexapis.com/v1/videoMesh/triggerTest/clusters/{cluster_id}"
|
|
656
|
+
if json_body:
|
|
657
|
+
body = json.loads(json_body)
|
|
658
|
+
else:
|
|
659
|
+
body = {}
|
|
660
|
+
if type_param is not None:
|
|
661
|
+
body["type"] = type_param
|
|
662
|
+
try:
|
|
663
|
+
result = api.session.rest_post(url, json=body)
|
|
664
|
+
except WebexError as e:
|
|
665
|
+
handle_rest_error(e)
|
|
666
|
+
if output == "json":
|
|
667
|
+
print_json(result)
|
|
668
|
+
elif isinstance(result, dict) and "id" in result:
|
|
669
|
+
typer.echo(f"Created: {result['id']}")
|
|
670
|
+
elif not result or result == {}:
|
|
671
|
+
typer.echo("Created.")
|
|
672
|
+
else:
|
|
673
|
+
print_json(result)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
@app.command("create-nodes")
|
|
678
|
+
def create_nodes(
|
|
679
|
+
node_id: str = typer.Argument(help="nodeId"),
|
|
680
|
+
type_param: str = typer.Option(None, "--type", help="Choices: ReachabilityTest, NetworkTest, MediaHealthMonitorTest"),
|
|
681
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
682
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
683
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
684
|
+
):
|
|
685
|
+
"""Trigger on-demand test for node."""
|
|
686
|
+
api = get_api(debug=debug)
|
|
687
|
+
url = f"https://webexapis.com/v1/videoMesh/triggerTest/nodes/{node_id}"
|
|
688
|
+
if json_body:
|
|
689
|
+
body = json.loads(json_body)
|
|
690
|
+
else:
|
|
691
|
+
body = {}
|
|
692
|
+
if type_param is not None:
|
|
693
|
+
body["type"] = type_param
|
|
694
|
+
try:
|
|
695
|
+
result = api.session.rest_post(url, json=body)
|
|
696
|
+
except WebexError as e:
|
|
697
|
+
handle_rest_error(e)
|
|
698
|
+
if output == "json":
|
|
699
|
+
print_json(result)
|
|
700
|
+
elif isinstance(result, dict) and "id" in result:
|
|
701
|
+
typer.echo(f"Created: {result['id']}")
|
|
702
|
+
elif not result or result == {}:
|
|
703
|
+
typer.echo("Created.")
|
|
704
|
+
else:
|
|
705
|
+
print_json(result)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
@app.command("list-test-status")
|
|
710
|
+
def list_test_status(
|
|
711
|
+
command_id: str = typer.Option(..., "--command-id", help="The unique command ID generated from Trigger on-demand test"),
|
|
712
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
713
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
714
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
715
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
716
|
+
):
|
|
717
|
+
"""Get Triggered test status."""
|
|
718
|
+
api = get_api(debug=debug)
|
|
719
|
+
url = f"https://webexapis.com/v1/videoMesh/testStatus"
|
|
720
|
+
params = {}
|
|
721
|
+
if command_id is not None:
|
|
722
|
+
params["commandId"] = command_id
|
|
723
|
+
if limit > 0:
|
|
724
|
+
params["max"] = limit
|
|
725
|
+
if offset > 0:
|
|
726
|
+
params["start"] = offset
|
|
727
|
+
result = None
|
|
728
|
+
try:
|
|
729
|
+
result = api.session.rest_get(url, params=params)
|
|
730
|
+
except WebexError as e:
|
|
731
|
+
handle_rest_error(e)
|
|
732
|
+
result = result or []
|
|
733
|
+
items = result.get("nodes", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
734
|
+
if output == "json":
|
|
735
|
+
print_json(items)
|
|
736
|
+
else:
|
|
737
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
@app.command("list-test-results")
|
|
742
|
+
def list_test_results(
|
|
743
|
+
command_id: str = typer.Option(..., "--command-id", help="The unique command ID generated from Trigger on-demand test"),
|
|
744
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
745
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
746
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
747
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
748
|
+
):
|
|
749
|
+
"""Get Triggered test results."""
|
|
750
|
+
api = get_api(debug=debug)
|
|
751
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults"
|
|
752
|
+
params = {}
|
|
753
|
+
if command_id is not None:
|
|
754
|
+
params["commandId"] = command_id
|
|
755
|
+
if limit > 0:
|
|
756
|
+
params["max"] = limit
|
|
757
|
+
if offset > 0:
|
|
758
|
+
params["start"] = offset
|
|
759
|
+
result = None
|
|
760
|
+
try:
|
|
761
|
+
result = api.session.rest_get(url, params=params)
|
|
762
|
+
except WebexError as e:
|
|
763
|
+
handle_rest_error(e)
|
|
764
|
+
result = result or []
|
|
765
|
+
items = result.get("results", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
766
|
+
if output == "json":
|
|
767
|
+
print_json(items)
|
|
768
|
+
else:
|
|
769
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
@app.command("list-network-test")
|
|
774
|
+
def list_network_test(
|
|
775
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
776
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
777
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
778
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
779
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
780
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
781
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
782
|
+
):
|
|
783
|
+
"""List Network Test results."""
|
|
784
|
+
api = get_api(debug=debug)
|
|
785
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/networkTest"
|
|
786
|
+
params = {}
|
|
787
|
+
if trigger_type is not None:
|
|
788
|
+
params["triggerType"] = trigger_type
|
|
789
|
+
if from_param is not None:
|
|
790
|
+
params["from"] = from_param
|
|
791
|
+
if to is not None:
|
|
792
|
+
params["to"] = to
|
|
793
|
+
if limit > 0:
|
|
794
|
+
params["max"] = limit
|
|
795
|
+
if offset > 0:
|
|
796
|
+
params["start"] = offset
|
|
797
|
+
org_id = get_org_id()
|
|
798
|
+
if org_id is not None:
|
|
799
|
+
params["orgId"] = org_id
|
|
800
|
+
result = None
|
|
801
|
+
try:
|
|
802
|
+
result = api.session.rest_get(url, params=params)
|
|
803
|
+
except WebexError as e:
|
|
804
|
+
handle_rest_error(e)
|
|
805
|
+
result = result or []
|
|
806
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
807
|
+
if output == "json":
|
|
808
|
+
print_json(items)
|
|
809
|
+
else:
|
|
810
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
@app.command("list-clusters-network-test")
|
|
815
|
+
def list_clusters_network_test(
|
|
816
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="Unique ID of the Video Mesh cluster."),
|
|
817
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
818
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
819
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
820
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
821
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
822
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
823
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
824
|
+
):
|
|
825
|
+
"""Get Network Test results for cluster."""
|
|
826
|
+
api = get_api(debug=debug)
|
|
827
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/networkTest/clusters"
|
|
828
|
+
params = {}
|
|
829
|
+
if cluster_id is not None:
|
|
830
|
+
params["clusterId"] = cluster_id
|
|
831
|
+
if trigger_type is not None:
|
|
832
|
+
params["triggerType"] = trigger_type
|
|
833
|
+
if from_param is not None:
|
|
834
|
+
params["from"] = from_param
|
|
835
|
+
if to is not None:
|
|
836
|
+
params["to"] = to
|
|
837
|
+
if limit > 0:
|
|
838
|
+
params["max"] = limit
|
|
839
|
+
if offset > 0:
|
|
840
|
+
params["start"] = offset
|
|
841
|
+
result = None
|
|
842
|
+
try:
|
|
843
|
+
result = api.session.rest_get(url, params=params)
|
|
844
|
+
except WebexError as e:
|
|
845
|
+
handle_rest_error(e)
|
|
846
|
+
result = result or []
|
|
847
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
848
|
+
if output == "json":
|
|
849
|
+
print_json(items)
|
|
850
|
+
else:
|
|
851
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
@app.command("list-nodes-network-test")
|
|
856
|
+
def list_nodes_network_test(
|
|
857
|
+
node_id: str = typer.Option(..., "--node-id", help="Unique ID of the Video Mesh node."),
|
|
858
|
+
trigger_type: str = typer.Option(..., "--trigger-type", help="Choices: OnDemand, Periodic, All"),
|
|
859
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
860
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
861
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
862
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
863
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
864
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
865
|
+
):
|
|
866
|
+
"""Get Network Test results for node."""
|
|
867
|
+
api = get_api(debug=debug)
|
|
868
|
+
url = f"https://webexapis.com/v1/videoMesh/testResults/networkTest/nodes"
|
|
869
|
+
params = {}
|
|
870
|
+
if node_id is not None:
|
|
871
|
+
params["nodeId"] = node_id
|
|
872
|
+
if trigger_type is not None:
|
|
873
|
+
params["triggerType"] = trigger_type
|
|
874
|
+
if from_param is not None:
|
|
875
|
+
params["from"] = from_param
|
|
876
|
+
if to is not None:
|
|
877
|
+
params["to"] = to
|
|
878
|
+
if limit > 0:
|
|
879
|
+
params["max"] = limit
|
|
880
|
+
if offset > 0:
|
|
881
|
+
params["start"] = offset
|
|
882
|
+
result = None
|
|
883
|
+
try:
|
|
884
|
+
result = api.session.rest_get(url, params=params)
|
|
885
|
+
except WebexError as e:
|
|
886
|
+
handle_rest_error(e)
|
|
887
|
+
result = result or []
|
|
888
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
889
|
+
if output == "json":
|
|
890
|
+
print_json(items)
|
|
891
|
+
else:
|
|
892
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
@app.command("list-client-type-distribution")
|
|
897
|
+
def list_client_type_distribution(
|
|
898
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
899
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
900
|
+
device_type: str = typer.Option(..., "--device-type", help="Device type(s). - Possible values: `webexDevices` `webexAp"),
|
|
901
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
902
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
903
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
904
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
905
|
+
):
|
|
906
|
+
"""List Cluster Client Type Distribution details."""
|
|
907
|
+
api = get_api(debug=debug)
|
|
908
|
+
url = f"https://webexapis.com/v1/videoMesh/clientTypeDistribution"
|
|
909
|
+
params = {}
|
|
910
|
+
if from_param is not None:
|
|
911
|
+
params["from"] = from_param
|
|
912
|
+
if to is not None:
|
|
913
|
+
params["to"] = to
|
|
914
|
+
if device_type is not None:
|
|
915
|
+
params["deviceType"] = device_type
|
|
916
|
+
if limit > 0:
|
|
917
|
+
params["max"] = limit
|
|
918
|
+
if offset > 0:
|
|
919
|
+
params["start"] = offset
|
|
920
|
+
org_id = get_org_id()
|
|
921
|
+
if org_id is not None:
|
|
922
|
+
params["orgId"] = org_id
|
|
923
|
+
result = None
|
|
924
|
+
try:
|
|
925
|
+
result = api.session.rest_get(url, params=params)
|
|
926
|
+
except WebexError as e:
|
|
927
|
+
handle_rest_error(e)
|
|
928
|
+
result = result or []
|
|
929
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
930
|
+
if output == "json":
|
|
931
|
+
print_json(items)
|
|
932
|
+
else:
|
|
933
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
@app.command("list-clusters-client-type-distribution")
|
|
938
|
+
def list_clusters_client_type_distribution(
|
|
939
|
+
cluster_id: str = typer.Option(..., "--cluster-id", help="Unique ID of the Video Mesh cluster."),
|
|
940
|
+
from_param: str = typer.Option(..., "--from", help="The start date and time of the requested data in any [ISO 86"),
|
|
941
|
+
to: str = typer.Option(..., "--to", help="The end date and time of the requested data in any [ISO 8601"),
|
|
942
|
+
device_type: str = typer.Option(..., "--device-type", help="Device type(s). - Possible values: `webexDevices` `webe"),
|
|
943
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
944
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
945
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
946
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
947
|
+
):
|
|
948
|
+
"""Get Cluster Client Type Distribution details."""
|
|
949
|
+
api = get_api(debug=debug)
|
|
950
|
+
url = f"https://webexapis.com/v1/videoMesh/clientTypeDistribution/clusters"
|
|
951
|
+
params = {}
|
|
952
|
+
if cluster_id is not None:
|
|
953
|
+
params["clusterId"] = cluster_id
|
|
954
|
+
if from_param is not None:
|
|
955
|
+
params["from"] = from_param
|
|
956
|
+
if to is not None:
|
|
957
|
+
params["to"] = to
|
|
958
|
+
if device_type is not None:
|
|
959
|
+
params["deviceType"] = device_type
|
|
960
|
+
if limit > 0:
|
|
961
|
+
params["max"] = limit
|
|
962
|
+
if offset > 0:
|
|
963
|
+
params["start"] = offset
|
|
964
|
+
result = None
|
|
965
|
+
try:
|
|
966
|
+
result = api.session.rest_get(url, params=params)
|
|
967
|
+
except WebexError as e:
|
|
968
|
+
handle_rest_error(e)
|
|
969
|
+
result = result or []
|
|
970
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
971
|
+
if output == "json":
|
|
972
|
+
print_json(items)
|
|
973
|
+
else:
|
|
974
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
@app.command("list-event-thresholds")
|
|
979
|
+
def list_event_thresholds(
|
|
980
|
+
event_name: str = typer.Option(None, "--event-name", help="Choices: clusterCallsRedirected, orgCallsOverflowed"),
|
|
981
|
+
cluster_id: str = typer.Option(None, "--cluster-id", help="Unique ID of the Video Mesh Cluster."),
|
|
982
|
+
event_scope: str = typer.Option(None, "--event-scope", help="Choices: CLUSTER, ORG"),
|
|
983
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
984
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
985
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
986
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
987
|
+
):
|
|
988
|
+
"""List Event Threshold Configuration."""
|
|
989
|
+
api = get_api(debug=debug)
|
|
990
|
+
url = f"https://webexapis.com/v1/videoMesh/eventThresholds"
|
|
991
|
+
params = {}
|
|
992
|
+
if event_name is not None:
|
|
993
|
+
params["eventName"] = event_name
|
|
994
|
+
if cluster_id is not None:
|
|
995
|
+
params["clusterId"] = cluster_id
|
|
996
|
+
if event_scope is not None:
|
|
997
|
+
params["eventScope"] = event_scope
|
|
998
|
+
if limit > 0:
|
|
999
|
+
params["max"] = limit
|
|
1000
|
+
if offset > 0:
|
|
1001
|
+
params["start"] = offset
|
|
1002
|
+
org_id = get_org_id()
|
|
1003
|
+
if org_id is not None:
|
|
1004
|
+
params["orgId"] = org_id
|
|
1005
|
+
result = None
|
|
1006
|
+
try:
|
|
1007
|
+
result = api.session.rest_get(url, params=params)
|
|
1008
|
+
except WebexError as e:
|
|
1009
|
+
handle_rest_error(e)
|
|
1010
|
+
result = result or []
|
|
1011
|
+
items = result.get("eventThresholds", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1012
|
+
if output == "json":
|
|
1013
|
+
print_json(items)
|
|
1014
|
+
else:
|
|
1015
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name')], limit=limit)
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
@app.command("update")
|
|
1020
|
+
def update(
|
|
1021
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1022
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1023
|
+
):
|
|
1024
|
+
"""Update Event Threshold Configuration\n\nExample --json-body:\n '{"eventThresholds":[{"eventThresholdId":"...","thresholdConfig":"..."}]}'."""
|
|
1025
|
+
api = get_api(debug=debug)
|
|
1026
|
+
url = f"https://webexapis.com/v1/videoMesh/eventThresholds"
|
|
1027
|
+
if json_body:
|
|
1028
|
+
body = json.loads(json_body)
|
|
1029
|
+
else:
|
|
1030
|
+
body = {}
|
|
1031
|
+
try:
|
|
1032
|
+
result = api.session.rest_patch(url, json=body)
|
|
1033
|
+
except WebexError as e:
|
|
1034
|
+
handle_rest_error(e)
|
|
1035
|
+
typer.echo(f"Updated.")
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
@app.command("show-event-thresholds")
|
|
1040
|
+
def show_event_thresholds(
|
|
1041
|
+
event_threshold_id: str = typer.Argument(help="eventThresholdId"),
|
|
1042
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1043
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1044
|
+
):
|
|
1045
|
+
"""Get Event Threshold Configuration."""
|
|
1046
|
+
api = get_api(debug=debug)
|
|
1047
|
+
url = f"https://webexapis.com/v1/videoMesh/eventThresholds/{event_threshold_id}"
|
|
1048
|
+
try:
|
|
1049
|
+
result = api.session.rest_get(url)
|
|
1050
|
+
except WebexError as e:
|
|
1051
|
+
handle_rest_error(e)
|
|
1052
|
+
if output == "json":
|
|
1053
|
+
print_json(result)
|
|
1054
|
+
else:
|
|
1055
|
+
if isinstance(result, dict):
|
|
1056
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1057
|
+
elif isinstance(result, list):
|
|
1058
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1059
|
+
else:
|
|
1060
|
+
print_json(result)
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
@app.command("create-reset")
|
|
1065
|
+
def create_reset(
|
|
1066
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1067
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1068
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1069
|
+
):
|
|
1070
|
+
"""Reset Event Threshold Configuration\n\nExample --json-body:\n '{"eventThresholdIds":["..."]}'."""
|
|
1071
|
+
api = get_api(debug=debug)
|
|
1072
|
+
url = f"https://webexapis.com/v1/videoMesh/eventThresholds/reset"
|
|
1073
|
+
if json_body:
|
|
1074
|
+
body = json.loads(json_body)
|
|
1075
|
+
else:
|
|
1076
|
+
body = {}
|
|
1077
|
+
try:
|
|
1078
|
+
result = api.session.rest_post(url, json=body)
|
|
1079
|
+
except WebexError as e:
|
|
1080
|
+
handle_rest_error(e)
|
|
1081
|
+
if output == "json":
|
|
1082
|
+
print_json(result)
|
|
1083
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1084
|
+
typer.echo(f"Created: {result['id']}")
|
|
1085
|
+
elif not result or result == {}:
|
|
1086
|
+
typer.echo("Created.")
|
|
1087
|
+
else:
|
|
1088
|
+
print_json(result)
|
|
1089
|
+
|
|
1090
|
+
|