Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ action_groups:
- container_repository
- container_sync
- deb_distribution
- deb_package
- deb_publication
- deb_remote
- deb_repository
Expand Down
145 changes: 145 additions & 0 deletions plugins/modules/deb_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/usr/bin/python

# copyright (c) 2026, Chris Taylor
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)


DOCUMENTATION = r"""
---
module: deb_package
short_description: Manage deb packages of a pulp api server instance
description:
- "This performs Create/Read/Remove operations on deb packages in the context of a repository."
options:
sha256:
description:
- sha256 digest of the deb package content to query or manipulate
type: str
aliases:
- digest
file:
description:
- A path to a file to be uploaded as the new package.
- Alternatively this is used to calculate the checksum of the file to be removed.
type: path
chunk_size:
description:
- Chunk size in bytes used to upload the file.
type: int
default: 33554432
repository:
description:
- The repository in which the content should be present or absent.
type: str
extends_documentation_fragment:
- pulp.squeezer.pulp.entity_state
- pulp.squeezer.pulp
author:
- Chris Taylor (@chtaylo2)
- Jacob Floyd (@cognifloyd)
- Daniel Ziegenberg (@ziegenberg)
- Matthias Dellweg (@mdellweg)
"""

EXAMPLES = r"""
- name: "Read list of deb packages from pulp api server"
deb_package:
api_url: "localhost:24817"
username: "admin"
password: "password"
register: "content_status"
- name: "Report pulp deb packages"
debug:
var: "content_status"
- name: "Create a deb package"
deb_package:
api_url: "localhost:24817"
username: "admin"
password: "password"
sha256: "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff"
file: "data/important_package.deb"
repository: "target_repository"
state: "present"
"""

RETURN = r"""
packages:
description: "List of deb packages"
type: "list"
returned: "when digest and file are not given"
package:
description: "The deb package details"
type: "dict"
returned: "when digest or file are given"
"""

import os
import traceback

from ansible_collections.pulp.squeezer.plugins.module_utils.pulp_glue import (
PulpEntityAnsibleModule,
SqueezerException,
)

try:
from pulp_glue.deb.context import PulpAptRepositoryContext, PulpDebPackageContext

PULP_GLUE_IMPORT_ERR = None

except ImportError:
PULP_GLUE_IMPORT_ERR = traceback.format_exc()
PulpDebPackageContext = None


def main():
with PulpEntityAnsibleModule(
context_class=PulpDebPackageContext,
entity_singular="package",
entity_plural="packages",
import_errors=[("pulp-glue-deb", PULP_GLUE_IMPORT_ERR)],
argument_spec={
"sha256": {"aliases": ["digest"]},
"file": {"type": "path"},
"chunk_size": {"type": "int", "default": 33554432},
"repository": {},
},
required_if=[
("state", "present", ["file", "repository"]),
("state", "absesent", ["repository"]),
],
) as module:
sha256 = module.params["sha256"]
if module.params["file"]:
if not os.path.exists(module.params["file"]):
raise SqueezerException("File not found.")
file_sha256 = module.sha256(module.params["file"])
if sha256:
if sha256 != file_sha256:
raise SqueezerException("File checksum mismatch.")
else:
sha256 = file_sha256

if sha256 is None and module.state == "absent":
raise SqueezerException(
"One of 'file' and 'sha256' is required if 'state' is 'absent'."
)

natural_key = {
"sha256": sha256,
}
desired_attributes = {}
defaults = {
"file": module.params["file"],
"chunk_size": module.params["chunk_size"],
}

if module.params["repository"]:
module.context.repository_ctx = PulpAptRepositoryContext(
module.pulp_ctx, entity={"name": module.params["repository"]}
)

module.process(natural_key, desired_attributes, defaults=defaults)


if __name__ == "__main__":
main()
75,670 changes: 75,670 additions & 0 deletions tests/fixtures/deb_package-0.yml

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions tests/fixtures/deb_package-1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
interactions:
- request:
body: null
headers:
? !!python/object/apply:multidict._multidict.istr
- Accept
: - application/json
Accept-Encoding:
- gzip, deflate, zstd
Connection:
- keep-alive
? !!python/object/apply:multidict._multidict.istr
- User-Agent
: - Squeezer/0.5.0-dev
method: GET
uri: http://pulp.example.org/pulp/api/v3/repositories/deb/apt/?name=test_deb_repository&offset=0&limit=1
response:
body:
string: '{"count":1,"next":null,"previous":null,"results":[{"pulp_href":"/pulp/api/v3/repositories/deb/apt/019eb35f-17ba-708e-b988-38a74aba420b/","prn":"prn:deb.aptrepository:019eb35f-17ba-708e-b988-38a74aba420b","pulp_created":"2026-06-10T21:10:14.203257Z","pulp_last_updated":"2026-06-10T21:10:24.221402Z","versions_href":"/pulp/api/v3/repositories/deb/apt/019eb35f-17ba-708e-b988-38a74aba420b/versions/","pulp_labels":{},"latest_version_href":"/pulp/api/v3/repositories/deb/apt/019eb35f-17ba-708e-b988-38a74aba420b/versions/1/","name":"test_deb_repository","description":null,"retain_repo_versions":null,"remote":null,"autopublish":false,"publish_upstream_release_fields":true,"signing_service":null,"signing_service_release_overrides":{}}]}'
headers:
Access-Control-Expose-Headers:
- Correlation-ID
Allow:
- GET, POST, HEAD, OPTIONS
Connection:
- keep-alive
Content-Length:
- '735'
Content-Type:
- application/json
Correlation-ID:
- ec83e8ea56d849059f0743968bff1546
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Wed, 10 Jun 2026 21:10:27 GMT
Referrer-Policy:
- same-origin
Server:
- nginx/1.22.1
Vary:
- Accept
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
status:
code: 200
message: OK
- request:
body: null
headers:
? !!python/object/apply:multidict._multidict.istr
- Accept
: - application/json
Accept-Encoding:
- gzip, deflate, zstd
Connection:
- keep-alive
? !!python/object/apply:multidict._multidict.istr
- Correlation-Id
: - ec83e8ea56d849059f0743968bff1546
? !!python/object/apply:multidict._multidict.istr
- User-Agent
: - Squeezer/0.5.0-dev
method: GET
uri: http://pulp.example.org/pulp/api/v3/content/deb/packages/?sha256=eb061a19af924d0add800ea5c86546d125f96454b45e60a541c205bdba5f6f6b&repository_version=%2Fpulp%2Fapi%2Fv3%2Frepositories%2Fdeb%2Fapt%2F019eb35f-17ba-708e-b988-38a74aba420b%2Fversions%2F1%2F&offset=0&limit=1
response:
body:
string: '{"count":1,"next":null,"previous":null,"results":[{"pulp_href":"/pulp/api/v3/content/deb/packages/019eb35f-3e94-7214-8036-d77c4dfeba21/","prn":"prn:deb.package:019eb35f-3e94-7214-8036-d77c4dfeba21","pulp_created":"2026-06-10T21:10:24.153728Z","pulp_last_updated":"2026-06-10T21:10:24.153749Z","pulp_labels":{},"vuln_report":null,"artifact":"/pulp/api/v3/artifacts/019eb35f-3dbf-7b1f-ae8f-d456872442cd/","relative_path":"pool/g/geirrodr/geirrodr_1.0_armeb.deb","md5":null,"sha1":null,"sha224":"4e7f5641b0c912087fdc42a99aa3226c984f38dc169f8387e4d36622","sha256":"eb061a19af924d0add800ea5c86546d125f96454b45e60a541c205bdba5f6f6b","sha384":"e44ba9043b39e09f7c086178e0fd51ef6bc61bcd40f6fb80d308b2e6cf025d34167f73906289dc771059813acae432af","sha512":"6adf58df1e40469bac2a7ee2cb170c0aba7eab4ec3596250258b2bb15ab184165d85450d486d0f7ada1552c2bef5b06377049b8894417e8bd92c08f7f8785afc","package":"geirrodr","source":null,"version":"1.0","architecture":"armeb","section":"misc","priority":"optional","origin":null,"tag":null,"bugs":null,"essential":null,"build_essential":null,"installed_size":"9","maintainer":"Equivs
Dummy Package Generator <root@bd208d733cce>","original_maintainer":null,"description":"Geirrodr\n
Geirrodr was a jotunn and the father of the giantesses Gjalp and Greip.","description_md5":null,"homepage":null,"built_using":null,"auto_built_package":null,"multi_arch":"foreign","breaks":null,"conflicts":null,"depends":null,"recommends":null,"suggests":null,"enhances":null,"pre_depends":null,"provides":null,"replaces":null}]}'
headers:
Access-Control-Expose-Headers:
- Correlation-ID
Allow:
- GET, POST, HEAD, OPTIONS
Connection:
- keep-alive
Content-Length:
- '1534'
Content-Type:
- application/json
Correlation-ID:
- ec83e8ea56d849059f0743968bff1546
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Wed, 10 Jun 2026 21:10:27 GMT
Referrer-Policy:
- same-origin
Server:
- nginx/1.22.1
Vary:
- Accept
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
status:
code: 200
message: OK
version: 1
Loading