From fd6396f93befcf2f5ba2c4e0d8da14cac80619bc Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Mon, 15 Jun 2026 14:44:32 -0500 Subject: [PATCH 1/7] feat: add package-change-plan API reference --- .../package-change-plans.md | 491 ++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 docs/reference/api/rest-api-endpoints/package-change-plans.md diff --git a/docs/reference/api/rest-api-endpoints/package-change-plans.md b/docs/reference/api/rest-api-endpoints/package-change-plans.md new file mode 100644 index 00000000..3bd50cd1 --- /dev/null +++ b/docs/reference/api/rest-api-endpoints/package-change-plans.md @@ -0,0 +1,491 @@ +--- +myst: + html_meta: + description: "REST API endpoints to create and manage package change plans in Landscape. Stage, inspect, and execute bulk package operations across a computer fleet." +--- + +(reference-rest-api-package-change-plans)= +# Package change plans + +The following endpoints are for creating, viewing, and deleting package change plans. Package change plans let you stage and review a bulk package operation across a fleet of computers before executing it. + +```{note} +TODO(srunde3): clarify point release version when finalized. + +You must be running the latest point release of Landscape Server 26.04 or above to use the REST API for package management. + +This feature is available on self-hosted and **select accounts on SaaS**. It is not generally available to all SaaS accounts. +``` + +## POST `/package-change-plans` + +Create a new package change plan. + +### Request body parameters + +**Required:** + +- `computer_query`: A query string that selects the target computers (uses the same syntax as the `query` parameter on {ref}`reference-rest-api-computers`). + +**Required--exactly one action config:** + +- `install_config`: Install packages. See [install_config](#install_config) below. +- `remove_config`: Remove packages. See [remove_config](#remove_config) below. +- `hold_config`: Hold packages at their current version. See [hold_config](#hold_config) below. +- `unhold_config`: Release held packages. See [unhold_config](#unhold_config) below. +- `upgrade_config`: Upgrade packages. See [upgrade_config](#upgrade_config) below. +- `change_version_config`: Change a package to a specific version. See [change_version_config](#change_version_config) below. + +### Response fields + +- `id`: UUID of the newly created plan. +- `state`: Lifecycle state of the plan. One of `created`, `started`, `completed`, `failed`. +- `action`: The package operation. One of `install`, `remove`, `hold`, `unhold`, `upgrade`, `change_version`. +- `created_at`: ISO 8601 timestamp of when the plan was created. +- `item_count`: Number of computer/package pairs targeted by the plan. + +(install_config)= +### `install_config` + +Installs packages on the target computers. Exactly one of `by_ids` or `latest_by_names` must be set. + +- `by_ids.package_ids`: List of package IDs to install. +- `latest_by_names.package_names`: List of package names whose latest available versions will be installed. + +Example request--install by name: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "install_config": { + "latest_by_names": { + "package_names": ["openssh-server", "curl"] + } + } + }' +``` + +Example request--install by ID: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "install_config": { + "by_ids": { + "package_ids": [101, 102] + } + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "install", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 50 +} +``` + +(remove_config)= +### `remove_config` + +Removes packages from the target computers. Exactly one of `by_ids` or `any_version_by_names` must be set. + +- `by_ids.package_ids`: List of package IDs to remove. +- `any_version_by_names.package_names`: List of package names to remove (any installed version). + +Example request--remove by name: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "remove_config": { + "any_version_by_names": { + "package_names": ["curl"] + } + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "remove", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 12 +} +``` + +(hold_config)= +### `hold_config` + +Holds packages at their current version, preventing automatic upgrades. + +- `package_ids` *(required)*: Non-empty list of package IDs to hold. + +Example request: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "hold_config": { + "package_ids": [101, 102] + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "hold", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 20 +} +``` + +(unhold_config)= +### `unhold_config` + +Releases held packages, allowing them to be upgraded again. + +- `package_ids` *(required)*: Non-empty list of package IDs to unhold. + +Example request: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "unhold_config": { + "package_ids": [101, 102] + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "unhold", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 20 +} +``` + +(upgrade_config)= +### `upgrade_config` + +Upgrades packages on the target computers. At least one selection criterion must be provided. `included_package_ids` cannot be combined with `select_all` or `select_all_security`. + +- `select_all`: If `true`, upgrade all upgradable packages. +- `select_all_security`: If `true`, upgrade all security-only upgradable packages. +- `included_package_ids`: Explicit list of package IDs to upgrade. +- `excluded_package_ids`: Package IDs to exclude when using `select_all` or `select_all_security`. + +Example request--upgrade all security packages: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "upgrade_config": { + "select_all_security": true + } + }' +``` + +Example request--upgrade specific packages by ID: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "upgrade_config": { + "included_package_ids": [101, 102] + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "upgrade", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 85 +} +``` + +(change_version_config)= +### `change_version_config` + +Changes targeted computers to a specific version of a package. + +- `package_ids` *(required)*: Non-empty list of package IDs whose version should be changed. + +Example request: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "change_version_config": { + "package_ids": [101] + } + }' +``` + +Example response (201 Created): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "change_version", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 10 +} +``` + +## GET `/package-change-plans/` + +Retrieve the status and metadata of a specific plan. + +Path parameters: + +- `id`: The UUID of the package change plan. + +Query parameters: + +- None + +Example request: + +```bash +curl -s -X GET "https://landscape.canonical.com/api/v2/package-change-plans/550e8400-e29b-41d4-a716-446655440000" \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" +``` + +Example response (200 OK): + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "state": "created", + "action": "install", + "created_at": "2026-01-15T10:00:00+00:00", + "item_count": 50 +} +``` + +## POST `/package-change-plans/:execute` + +Execute a package change plan, creating activities for every targeted computer. + +Path parameters: + +- `id`: The UUID of the package change plan. + +Query parameters: + +- None + +Request body: + +- None + +Example request: + +```bash +curl -s -X POST "https://landscape.canonical.com/api/v2/package-change-plans/550e8400-e29b-41d4-a716-446655440000:execute" \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" +``` + +Example response (200 OK): + +```json +{ + "id": 42, + "summary": "Install packages on selected computers", + "type": "PackageChangePlanActivity", + "deliver_delay_window": 0, + "creator": { + "id": 1, + "name": "John Smith", + "email": "john@example.com" + }, + "activity_status": "pending" +} +``` + +The response is a parent activity that tracks the overall execution. Child activities are created for each targeted computer. + +## GET `/package-change-plans//items` + +List the individual computer/package pairs within a plan. + +Path parameters: + +- `id`: The UUID of the package change plan. + +Query parameters: + +- `computer_ids`: Comma-separated list of computer IDs to filter by (optional). +- `package_ids`: Comma-separated list of package IDs to filter by (optional). +- `computer_instance_name`: Filter by a computer's instance name (optional). +- `limit`: Maximum number of results to return (optional). +- `offset`: Offset into the result list (default: `0`). + +Example request: + +```bash +curl -s -X GET "https://landscape.canonical.com/api/v2/package-change-plans/550e8400-e29b-41d4-a716-446655440000/items?limit=2" \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" +``` + +Example response (200 OK): + +```json +{ + "items": [ + { + "id": 1, + "package_id": 101, + "computer_id": 5 + }, + { + "id": 2, + "package_id": 102, + "computer_id": 7 + } + ], + "count": 2 +} +``` + +Response fields: + +- `items`: List of plan items. + - `id`: Sequential item ID within this response. + - `package_id`: ID of the package targeted by this item. + - `computer_id`: ID of the computer targeted by this item. +- `count`: Total number of items returned. + +## GET `/package-change-plans//summary` + +Get a per-package summary of applicable and non-applicable target states across the computer selection. + +Path parameters: + +- `id`: The UUID of the package change plan. + +Query parameters: + +- None + +Example request: + +```bash +curl -s -X GET "https://landscape.canonical.com/api/v2/package-change-plans/550e8400-e29b-41d4-a716-446655440000/summary" \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" +``` + +Example response (200 OK): + +```json +{ + "summary_items": [ + { + "package_id": 1, + "package_name": "openssh-server", + "package_version": "1:9.6p1-3ubuntu13.5", + "package_state_counts": [ + { + "state": "applicable", + "count": 48 + }, + { + "state": "not_applicable", + "count": 2 + } + ] + } + ] +} +``` + +Response fields: + +- `summary_items`: One entry per package included in the plan. + - `package_id`: ID of the package. + - `package_name`: Name of the package. + - `package_version`: Version string of the package. + - `package_state_counts`: List of state/count pairs describing the distribution of target states across the selected computers. + - `state`: Either `applicable` or `not_applicable`. + - `count`: Number of computers in this state. + +`applicable` means the operation will be performed on that computer. `not_applicable` means the operation will not. + +## DELETE `/package-change-plans/` + +Delete a package change plan. + +Path parameters: + +- `id`: The UUID of the package change plan. + +Query parameters: + +- None + +Request body: + +- None + +Example request: + +```bash +curl -s -X DELETE "https://landscape.canonical.com/api/v2/package-change-plans/550e8400-e29b-41d4-a716-446655440000" \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" +``` + +Response: 204 No Content (empty body). From 933ede1c01c8e53571b6d1dd9b7e0af075064bcc Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Mon, 15 Jun 2026 14:51:52 -0500 Subject: [PATCH 2/7] feat: add package-search API reference --- .../api/rest-api-endpoints/package-search.md | 208 ++++++++++++++++++ .../api/rest-api-endpoints/packages.md | 4 + 2 files changed, 212 insertions(+) create mode 100644 docs/reference/api/rest-api-endpoints/package-search.md diff --git a/docs/reference/api/rest-api-endpoints/package-search.md b/docs/reference/api/rest-api-endpoints/package-search.md new file mode 100644 index 00000000..87f9986f --- /dev/null +++ b/docs/reference/api/rest-api-endpoints/package-search.md @@ -0,0 +1,208 @@ +--- +myst: + html_meta: + description: "REST API endpoints to search packages and vulnerabilities across a computer fleet in Landscape." +--- + +(reference-rest-api-package-search)= +# Package search + +These endpoints search for packages and vulnerabilities across a computer selection. Both accept the same core set of filters and return per-package state counts aggregated across the targeted computers. + +```{note} +TODO(srunde3): clarify point release version when finalized. + +You must be running the latest point release of Landscape Server 26.04 or above to use the REST API for package management. + +This feature is available on self-hosted and **select accounts on SaaS**. It is not generally available to all SaaS accounts. +``` + +### Filter state values + +Several parameters use a tri-state filter. Accepted values are: + +- `true` -- include only items matching this condition. +- `false` -- exclude items matching this condition. +- `unspecified` *(default)* -- do not filter on this condition. + +## POST `/packages:search` + +Search for packages across a computer selection. + +### Request body parameters + +**Required:** + +- `computer_query`: A query string that selects the target computers (uses the same syntax as the `query` parameter on {ref}`reference-rest-api-computers`). + +**Optional:** + +- `text`: Free-text search string. Matches against all package fields, including description. +- `names`: Comma-separated list of package names to restrict the search to. +- `installed`: Filter by installed state. See [filter state values](#filter-state-values) above. +- `available`: Filter by availability in an APT source. See [filter state values](#filter-state-values) above. +- `upgrade`: Filter by whether a newer version is available. See [filter state values](#filter-state-values) above. +- `held`: Filter by whether the package is held on computers. See [filter state values](#filter-state-values) above. +- `security`: Filter by security upgrade availability. See [filter state values](#filter-state-values) above. +- `limit`: Maximum number of packages to return. +- `offset`: Offset into the result list (default: `0`). + +### Response fields + +- `packages`: List of matched packages. + - `id`: Package ID. + - `name`: Package name. + - `summary`: Short description of the package. + - `version`: Package version string. + - `package_state_counts`: Counts of computers in each state for this package. + - `available`: Number of computers where the package is available. + - `held`: Number of computers where the package is held. + - `upgrade_available`: Number of computers where an upgrade is available. + - `installed`: Number of computers where the package is installed. +- `computer_selection_stats`: Aggregate stats for the computer selection. + - `total_count`: Total number of computers matched by `computer_query`. + - `no_results_count`: Number of matched computers that returned no packages. +- `count`: Total number of packages matching the query. +- `next`: URL for the next page of results, or `null` if there are no more results. +- `prev`: URL for the previous page of results, or `null` if on the first page. + +### Example + +Example request: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/packages:search \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "text": "ssh", + "installed": "true", + "limit": 2 + }' +``` + +Example response (200 OK): + +```json +{ + "packages": [ + { + "id": 1, + "name": "openssh-server", + "summary": "secure shell (SSH) server, for secure access from remote machines", + "version": "1:9.6p1-3ubuntu13.5", + "package_state_counts": { + "available": 50, + "held": 2, + "upgrade_available": 10, + "installed": 48 + } + } + ], + "computer_selection_stats": { + "total_count": 50, + "no_results_count": 2 + }, + "count": 1, + "next": null, + "prev": null +} +``` + +## POST `/packages:search-vulnerabilities` + +Search for packages with known security vulnerabilities across a computer selection. Returns packages matching the query and their associated with CVEs or Ubuntu Security Notices (USNs), if any. + +### Request body parameters + +**Required:** + +- `computer_query`: A query string that selects the target computers (uses the same syntax as the `query` parameter on {ref}`reference-rest-api-computers`). + +**Optional:** + +- `text`: Free-text search string. Matches against all package fields, including description. +- `names`: Comma-separated list of package names to restrict the search to. +- `installed`: Filter by installed state. See [filter state values](#filter-state-values) above. +- `available`: Filter by availability in an APT source. See [filter state values](#filter-state-values) above. +- `upgrade`: Filter by whether a newer version is available. See [filter state values](#filter-state-values) above. +- `held`: Filter by whether the package is held on computers. See [filter state values](#filter-state-values) above. +- `security`: Filter by security upgrade availability. See [filter state values](#filter-state-values) above. +- `limit`: Maximum number of packages to return. +- `offset`: Offset into the result list (default: `0`). + +### Response fields + +- `vulnerable_packages`: List of packages with known vulnerabilities. + - `package`: Package details (same fields as in `/packages:search`). + - `cve_ids`: List of CVE identifiers associated with this package (e.g. `CVE-2024-6387`). + - `usn_ids`: List of Ubuntu Security Notice identifiers associated with this package (e.g. `USN-6859-1`). +- `computer_selection_stats`: Aggregate stats for the computer selection. + - `total_count`: Total number of computers matched by `computer_query`. + - `no_results_count`: Number of matched computers that returned no packages. +- `count`: Total number of vulnerable packages matching the query. +- `next`: URL for the next page of results, or `null` if there are no more results. +- `prev`: URL for the previous page of results, or `null` if on the first page. + +### Example + +Example request: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/packages:search-vulnerabilities \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "installed": "true" + }' +``` + +Example response (200 OK): + +```json +{ + "vulnerable_packages": [ + { + "package": { + "id": 1, + "name": "openssh-server", + "summary": "secure shell (SSH) server, for secure access from remote machines", + "version": "1:9.6p1-3ubuntu13.5", + "package_state_counts": { + "available": 50, + "held": 2, + "upgrade_available": 10, + "installed": 48 + } + }, + "cve_ids": ["CVE-2024-6387", "CVE-2023-51385"], + "usn_ids": ["USN-6859-1", "USN-6560-1"] + }, + { + "package": { + "id": 3, + "name": "curl", + "summary": "command line tool for transferring data with URL syntax", + "version": "8.5.0-2ubuntu10.6", + "package_state_counts": { + "available": 50, + "held": 1, + "upgrade_available": 3, + "installed": 49 + } + }, + "cve_ids": ["CVE-2024-2466"], + "usn_ids": ["USN-6936-1"] + } + ], + "computer_selection_stats": { + "total_count": 50, + "no_results_count": 2 + }, + "count": 2, + "next": null, + "prev": null +} +``` diff --git a/docs/reference/api/rest-api-endpoints/packages.md b/docs/reference/api/rest-api-endpoints/packages.md index 72df3ddf..887e88b1 100644 --- a/docs/reference/api/rest-api-endpoints/packages.md +++ b/docs/reference/api/rest-api-endpoints/packages.md @@ -7,6 +7,10 @@ myst: (reference-rest-api-packages)= # Packages +```{note} +TODO(srunde3): clarify deprecation or this API or a preference for `POST /packages:search` once fully-released. +``` + ## GET `/packages` Get a list of packages that have been reported to this Landscape account. From 51e3e8a5114af05a886e555532362e6281e61dae Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Tue, 16 Jun 2026 12:57:50 -0500 Subject: [PATCH 3/7] update upgrade_config to use new schema --- .../package-change-plans.md | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/reference/api/rest-api-endpoints/package-change-plans.md b/docs/reference/api/rest-api-endpoints/package-change-plans.md index 3bd50cd1..cfd2cdee 100644 --- a/docs/reference/api/rest-api-endpoints/package-change-plans.md +++ b/docs/reference/api/rest-api-endpoints/package-change-plans.md @@ -201,12 +201,15 @@ Example response (201 Created): (upgrade_config)= ### `upgrade_config` -Upgrades packages on the target computers. At least one selection criterion must be provided. `included_package_ids` cannot be combined with `select_all` or `select_all_security`. +Upgrades packages on the target computers. Exactly one of `select_by_ids` or `select_by_category` must be set. -- `select_all`: If `true`, upgrade all upgradable packages. -- `select_all_security`: If `true`, upgrade all security-only upgradable packages. -- `included_package_ids`: Explicit list of package IDs to upgrade. -- `excluded_package_ids`: Package IDs to exclude when using `select_all` or `select_all_security`. +- `select_by_ids`: Upgrade specific packages by ID. + - `package_ids` *(required)*: Non-empty list of package IDs to upgrade. +- `select_by_category`: Upgrade all packages in a given category, optionally excluding selected IDs. + - `category` *(required)*: Which packages to upgrade. One of: + - `all`: all upgradable packages, including security packages. + - `all_security`: only upgradable security packages. + - `excluded_package_ids`: Package IDs to exclude from the category (default: `[]`). Example request--upgrade all security packages: @@ -217,7 +220,26 @@ curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ -d '{ "computer_query": "tag:production", "upgrade_config": { - "select_all_security": true + "select_by_category": { + "category": "all_security" + } + } + }' +``` + +Example request--upgrade all security packages, excluding specific IDs: + +```bash +curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ + -H "Authorization: Bearer $JWT" \ + -H "Content-Type: application/json" \ + -d '{ + "computer_query": "tag:production", + "upgrade_config": { + "select_by_category": { + "category": "all_security", + "excluded_package_ids": [99] + } } }' ``` @@ -231,7 +253,9 @@ curl -s -X POST https://landscape.canonical.com/api/v2/package-change-plans \ -d '{ "computer_query": "tag:production", "upgrade_config": { - "included_package_ids": [101, 102] + "select_by_ids": { + "package_ids": [101, 102] + } } }' ``` From 30d4c5dce9c69127cc7bb4205485d7175b4e3079 Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Thu, 18 Jun 2026 16:55:58 -0500 Subject: [PATCH 4/7] update package search API to use consolidated packages response --- .../api/rest-api-endpoints/package-search.md | 104 +++++++++--------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/docs/reference/api/rest-api-endpoints/package-search.md b/docs/reference/api/rest-api-endpoints/package-search.md index 87f9986f..fbf97d86 100644 --- a/docs/reference/api/rest-api-endpoints/package-search.md +++ b/docs/reference/api/rest-api-endpoints/package-search.md @@ -54,14 +54,13 @@ Search for packages across a computer selection. - `name`: Package name. - `summary`: Short description of the package. - `version`: Package version string. - - `package_state_counts`: Counts of computers in each state for this package. - - `available`: Number of computers where the package is available. - - `held`: Number of computers where the package is held. - - `upgrade_available`: Number of computers where an upgrade is available. - - `installed`: Number of computers where the package is installed. -- `computer_selection_stats`: Aggregate stats for the computer selection. - - `total_count`: Total number of computers matched by `computer_query`. - - `no_results_count`: Number of matched computers that returned no packages. + - `computers`: Number of computers matching the query that have this package. + - `count`: Count of matching computers. + - `usn`: Associated Ubuntu Security Notice, if any. + - `id`: USN identifier. + - `summary`: Optional USN summary. + - `cves`: Associated CVEs, if any. + - `id`: CVE identifier. - `count`: Total number of packages matching the query. - `next`: URL for the next page of results, or `null` if there are no more results. - `prev`: URL for the previous page of results, or `null` if on the first page. @@ -92,18 +91,11 @@ Example response (200 OK): "name": "openssh-server", "summary": "secure shell (SSH) server, for secure access from remote machines", "version": "1:9.6p1-3ubuntu13.5", - "package_state_counts": { - "available": 50, - "held": 2, - "upgrade_available": 10, - "installed": 48 + "computers": { + "count": 50 } } ], - "computer_selection_stats": { - "total_count": 50, - "no_results_count": 2 - }, "count": 1, "next": null, "prev": null @@ -134,13 +126,18 @@ Search for packages with known security vulnerabilities across a computer select ### Response fields -- `vulnerable_packages`: List of packages with known vulnerabilities. - - `package`: Package details (same fields as in `/packages:search`). - - `cve_ids`: List of CVE identifiers associated with this package (e.g. `CVE-2024-6387`). - - `usn_ids`: List of Ubuntu Security Notice identifiers associated with this package (e.g. `USN-6859-1`). -- `computer_selection_stats`: Aggregate stats for the computer selection. - - `total_count`: Total number of computers matched by `computer_query`. - - `no_results_count`: Number of matched computers that returned no packages. +- `packages`: List of packages with known vulnerabilities. + - `id`: Package ID. + - `name`: Package name. + - `summary`: Short description of the package. + - `version`: Package version string. + - `computers`: Number of computers matching the query that have this package. + - `count`: Count of matching computers. + - `usn`: Associated Ubuntu Security Notice, if any. + - `id`: USN identifier. + - `summary`: Optional USN summary. + - `cves`: Associated CVEs, if any. + - `id`: CVE identifier. - `count`: Total number of vulnerable packages matching the query. - `next`: URL for the next page of results, or `null` if there are no more results. - `prev`: URL for the previous page of results, or `null` if on the first page. @@ -163,44 +160,41 @@ Example response (200 OK): ```json { - "vulnerable_packages": [ + "packages": [ { - "package": { - "id": 1, - "name": "openssh-server", - "summary": "secure shell (SSH) server, for secure access from remote machines", - "version": "1:9.6p1-3ubuntu13.5", - "package_state_counts": { - "available": 50, - "held": 2, - "upgrade_available": 10, - "installed": 48 - } + "id": 1, + "name": "openssh-server", + "summary": "secure shell (SSH) server, for secure access from remote machines", + "version": "1:9.6p1-3ubuntu13.5", + "computers": { + "count": 50 }, - "cve_ids": ["CVE-2024-6387", "CVE-2023-51385"], - "usn_ids": ["USN-6859-1", "USN-6560-1"] + "cves": [ + {"id": "CVE-2024-6387"}, + {"id": "CVE-2023-51385"} + ], + "usn": { + "id": "USN-6859-1", + "summary": null + } }, { - "package": { - "id": 3, - "name": "curl", - "summary": "command line tool for transferring data with URL syntax", - "version": "8.5.0-2ubuntu10.6", - "package_state_counts": { - "available": 50, - "held": 1, - "upgrade_available": 3, - "installed": 49 - } + "id": 3, + "name": "curl", + "summary": "command line tool for transferring data with URL syntax", + "version": "8.5.0-2ubuntu10.6", + "computers": { + "count": 50 }, - "cve_ids": ["CVE-2024-2466"], - "usn_ids": ["USN-6936-1"] + "cves": [ + {"id": "CVE-2024-2466"} + ], + "usn": { + "id": "USN-6936-1", + "summary": null + } } ], - "computer_selection_stats": { - "total_count": 50, - "no_results_count": 2 - }, "count": 2, "next": null, "prev": null From 59670cce7374f8d973e290d1f0c54f3021388da6 Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Wed, 24 Jun 2026 11:25:20 -0500 Subject: [PATCH 5/7] fix: package upgrade search instead of vulnerability search --- .../api/rest-api-endpoints/package-search.md | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/docs/reference/api/rest-api-endpoints/package-search.md b/docs/reference/api/rest-api-endpoints/package-search.md index fbf97d86..17f0b072 100644 --- a/docs/reference/api/rest-api-endpoints/package-search.md +++ b/docs/reference/api/rest-api-endpoints/package-search.md @@ -1,13 +1,13 @@ --- myst: html_meta: - description: "REST API endpoints to search packages and vulnerabilities across a computer fleet in Landscape." + description: "REST API endpoints to search packages and upgrades across a computer fleet in Landscape." --- (reference-rest-api-package-search)= # Package search -These endpoints search for packages and vulnerabilities across a computer selection. Both accept the same core set of filters and return per-package state counts aggregated across the targeted computers. +These endpoints search for packages and upgrades across a computer selection. ```{note} TODO(srunde3): clarify point release version when finalized. @@ -43,7 +43,7 @@ Search for packages across a computer selection. - `available`: Filter by availability in an APT source. See [filter state values](#filter-state-values) above. - `upgrade`: Filter by whether a newer version is available. See [filter state values](#filter-state-values) above. - `held`: Filter by whether the package is held on computers. See [filter state values](#filter-state-values) above. -- `security`: Filter by security upgrade availability. See [filter state values](#filter-state-values) above. +- `security`: If `True`, restrict results to packages from a security pocket. If `False`, restrict results to packages not from a security pocket. See [filter state values](#filter-state-values) above. - `limit`: Maximum number of packages to return. - `offset`: Offset into the result list (default: `0`). @@ -102,9 +102,9 @@ Example response (200 OK): } ``` -## POST `/packages:search-vulnerabilities` +## POST `/packages:search-upgrades` -Search for packages with known security vulnerabilities across a computer selection. Returns packages matching the query and their associated with CVEs or Ubuntu Security Notices (USNs), if any. +Search for package upgrades across a computer selection. ### Request body parameters @@ -116,17 +116,13 @@ Search for packages with known security vulnerabilities across a computer select - `text`: Free-text search string. Matches against all package fields, including description. - `names`: Comma-separated list of package names to restrict the search to. -- `installed`: Filter by installed state. See [filter state values](#filter-state-values) above. -- `available`: Filter by availability in an APT source. See [filter state values](#filter-state-values) above. -- `upgrade`: Filter by whether a newer version is available. See [filter state values](#filter-state-values) above. -- `held`: Filter by whether the package is held on computers. See [filter state values](#filter-state-values) above. -- `security`: Filter by security upgrade availability. See [filter state values](#filter-state-values) above. +- `security`: Restrict results to packages from a security pocket. - `limit`: Maximum number of packages to return. - `offset`: Offset into the result list (default: `0`). ### Response fields -- `packages`: List of packages with known vulnerabilities. +- `packages`: List of upgradeable packages. - `id`: Package ID. - `name`: Package name. - `summary`: Short description of the package. @@ -138,7 +134,7 @@ Search for packages with known security vulnerabilities across a computer select - `summary`: Optional USN summary. - `cves`: Associated CVEs, if any. - `id`: CVE identifier. -- `count`: Total number of vulnerable packages matching the query. +- `count`: Total number of upgradeable packages matching the query. - `next`: URL for the next page of results, or `null` if there are no more results. - `prev`: URL for the previous page of results, or `null` if on the first page. @@ -147,12 +143,12 @@ Search for packages with known security vulnerabilities across a computer select Example request: ```bash -curl -s -X POST https://landscape.canonical.com/api/v2/packages:search-vulnerabilities \ +curl -s -X POST https://landscape.canonical.com/api/v2/packages:search-upgrades \ -H "Authorization: Bearer $JWT" \ -H "Content-Type: application/json" \ -d '{ "computer_query": "tag:production", - "installed": "true" + "security": "true" }' ``` From 917c5dee3c8aba6dee764c099f35ae03775de499 Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Thu, 25 Jun 2026 18:17:34 -0500 Subject: [PATCH 6/7] add explanation for change plan actions --- .../features/package-change-plans.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/explanation/features/package-change-plans.md diff --git a/docs/explanation/features/package-change-plans.md b/docs/explanation/features/package-change-plans.md new file mode 100644 index 00000000..2552164d --- /dev/null +++ b/docs/explanation/features/package-change-plans.md @@ -0,0 +1,65 @@ +--- +myst: + html_meta: + description: "Understand how package change plans work in Landscape, including how each action type resolves its input parameters into a set of planned operations." +--- + +(explanation-package-change-plans)= + +# Package change plans + +A package change plan is a staged set of package operations to be applied across a computer selection. When you create a plan, Landscape calculates which computers and packages are affected before any changes are made. You can inspect the plan, then execute it to trigger the underlying activities. + +Each plan has exactly one action, which determines how the set of affected (computer, package) pairs is resolved. + +## Actions + +### Install + +Install one or more packages across the computer selection. You can target packages by exact version or by name. + +**Targeting by exact version:** A computer is included if the specified version is available on that computer and not already installed. A computer is excluded if that version is already installed, or if the version is not available on that computer. + +**Targeting by name:** Landscape queries all known versions of each name and resolves which version to install per computer. Versions are considered newest-first. For each computer, Landscape installs the newest available version that is not already installed in any version. A computer is excluded if it already has any version of the package installed, or if no version of the package is available on it. + +### Remove + +Remove one or more packages across the computer selection. You can target packages by exact version or by name. + +A computer is included if the specified package is installed on it. A computer is excluded if the package is not installed. When targeting by name, any installed version matching the name is removed. + +### Hold + +Pin specific packages at their current version across the computer selection, preventing them from being upgraded. A computer is included if the package is installed and not already held on it. A computer is excluded if the package is not installed, or if it is already held. + +### Unhold + +Release a package from its version pin across the computer selection, allowing it to be upgraded again. A computer is included if the package is currently held on it. A computer is excluded if the package is not held. + +Packages cannot be held as "uninstalled". Only installed packages can be held by change plans. + +### Upgrade + +Upgrade packages across the computer selection. You can target a specific set of packages, or upgrade by category: + +- **All upgrades** -- every package with an available upgrade. +- **Security upgrades only** -- only packages with an upgrade available from a security pocket. + +When upgrading by category, you can also exclude specific packages from the upgrade set. + +### Change version + +Switch specific packages to a different version -- either an upgrade or a downgrade. Each operation maps a currently installed version to a desired target version. A computer is included if the current version is installed on it, the current version is not held, and the target version is available. A computer is excluded if the current version is not installed, the current version is held, or the target version is unavailable. + +## Plan items and the summary + +After creation, the plan contains a flat list of (computer, package) items, each representing one intended operation on one computer. Not every item will necessarily be executable. The plan summary groups items by package and breaks down counts by target state: + +- **Applicable** -- the operation can be performed on this computer. +- **Not applicable** -- the operation cannot be performed on this computer. + +Reviewing the summary before executing gives you visibility into the scope and impact of the plan. + +## Execution + +Executing a plan converts its applicable items into Landscape activities, which are then dispatched to the relevant computers. See {ref}`explanation-activities` for details on how activities progress through their lifecycle. From ec4810ada2245d1430600838b950c38e7cf688f8 Mon Sep 17 00:00:00 2001 From: Spencer Runde Date: Wed, 1 Jul 2026 12:17:09 -0500 Subject: [PATCH 7/7] return computer_ref object from change plan items --- .../package-change-plans.md | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/reference/api/rest-api-endpoints/package-change-plans.md b/docs/reference/api/rest-api-endpoints/package-change-plans.md index cfd2cdee..5db6f1a4 100644 --- a/docs/reference/api/rest-api-endpoints/package-change-plans.md +++ b/docs/reference/api/rest-api-endpoints/package-change-plans.md @@ -410,14 +410,20 @@ Example response (200 OK): { "items": [ { - "id": 1, "package_id": 101, - "computer_id": 5 + "computer": { + "id": 5, + "name": "web-server-01" + }, + "action": "install" }, { - "id": 2, "package_id": 102, - "computer_id": 7 + "computer": { + "id": 7, + "name": "db-server-01" + }, + "action": "install" } ], "count": 2 @@ -427,9 +433,11 @@ Example response (200 OK): Response fields: - `items`: List of plan items. - - `id`: Sequential item ID within this response. - `package_id`: ID of the package targeted by this item. - - `computer_id`: ID of the computer targeted by this item. + - `computer`: The computer targeted by this item. + - `id`: ID of the computer. + - `name`: Name of the computer. + - `action`: The package operation for this item. - `count`: Total number of items returned. ## GET `/package-change-plans//summary`