Skip to content

Add pulp_container_content role, module and test #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 11, 2023
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
push:
branches:
- master
env:
ANSIBLE_FORCE_COLOR: True

jobs:
lint:
Expand Down
2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace: "stackhpc"
name: "pulp"
version: "0.4.2"
version: "0.5.0"
readme: "README.md"
authors:
- "Piotr Parczewski"
Expand Down
189 changes: 189 additions & 0 deletions plugins/modules/pulp_container_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import absolute_import, division, print_function

__metaclass__ = type


DOCUMENTATION = r"""
---
module: pulp_container_content
short_description: Manage container content of a pulp api server instance
description:
- "This performs CRUD operations on container content in a pulp api server instance."
options:
allow_missing:
description:
- Whether to allow missing tags when state is present.
type: bool
default: false
src_repo:
description:
- Name of the repository to copy content from when state is present.
type: str
src_is_push:
description:
- Whether src_repo is a container-push repository.
type: bool
default: false
repository:
description:
- Name of the repository to add or remove content
type: str
required: true
tags:
description:
- List of tags to add or remove
type: list
items: str
required: true
extends_documentation_fragment:
- pulp.squeezer.pulp
- pulp.squeezer.pulp.entity_state
author:
- Mark Goddard (@markgoddard)
"""

EXAMPLES = r"""
- name: Copy tag1 and tag2 from repo1 to repo2
pulp_container_content:
pulp_url: https://pulp.example.org
username: admin
password: password
repository: repo2
src_repo: repo1
tags:
- tag1
- tag2

- name: Remove tag3 from repo3
pulp_container_content:
pulp_url: https://pulp.example.org
username: admin
password: password
repository: repo3
tags:
- tag3
state: absent
"""

RETURN = r"""
repository_version:
description: Created container repository version
type: dict
returned: when content is added or removed
"""


from ansible_collections.pulp.squeezer.plugins.module_utils.pulp import (
PAGE_LIMIT,
PulpContainerRepository,
PulpEntity,
PulpEntityAnsibleModule,
PulpTask,
SqueezerException,
)


class PulpContainerRepositoryContent(PulpContainerRepository):
_add_id = "repositories_container_container_add"
_remove_id = "repositories_container_container_remove"
_container_tags_list_id = "content_container_tags_list"

_name_singular = "repository_version"

def get_src_repo(self):
# Query source repository.
natural_key = {"name": self.module.params["src_repo"]}
repo = PulpContainerRepository(self.module, natural_key)
if self.module.params["state"] == "present" and self.module.params["src_is_push"]:
repo._list_id = "repositories_container_container_push_list"
# find populates repo.entity.
repo.find(failsafe=False)
return repo

def get_content_units(self, repo):
# Query container tags with matching names in repo.
# Pagination code adapted from PulpEntity.list().
tags = []
offset = 0
search_result = {"next": True}
while search_result["next"]:
parameters = {
"limit": PAGE_LIMIT,
"offset": offset,
"name__in": ",".join(self.module.params["tags"]),
"repository_version": repo.entity["latest_version_href"]
}
search_result = self.module.pulp_api.call(
self._container_tags_list_id, parameters=parameters
)
tags.extend(search_result["results"])
offset += PAGE_LIMIT

if (self.module.params["state"] == "present" and
not self.module.params["allow_missing"] and
len(tags) != len(self.module.params["tags"])):
missing = ", ".join(set(self.module.params["tags"]) - set(tags))
raise SqueezerException(f"Some tags not found in source repository: {missing}")
return [result["pulp_href"] for result in tags]

def add_or_remove(self, add_or_remove_id, content_units):
body = {"content_units": content_units}
if not self.module.check_mode:
parameters = {"container_container_repository_href": self.entity["pulp_href"]}
response = self.module.pulp_api.call(
add_or_remove_id, body=body, uploads=self.uploads, parameters=parameters
)
if response and "task" in response:
task = PulpTask(self.module, {"pulp_href": response["task"]}).wait_for()
# Adding or removing content results in creation of a new repository version
if task["created_resources"]:
self.entity = {"pulp_href": task["created_resources"][0]}
self.module.set_changed()
else:
self.entity = None
else:
self.entity = response
else:
# Assume changed in check mode
self.module.set_changed()

def add(self):
src_repo = self.get_src_repo()
self.add_or_remove(self._add_id, self.get_content_units(src_repo))

def remove(self):
self.add_or_remove(self._remove_id, self.get_content_units(self))

def process(self):
# Populate self.entity.
self.find(failsafe=False)
if self.module.params["state"] == "present":
response = self.add()
elif self.module.params["state"] == "absent":
response = self.remove()
else:
raise SqueezerException("Unexpected state")
self.module.set_result(self._name_singular, self.presentation(self.entity))


def main():
with PulpEntityAnsibleModule(
argument_spec=dict(
allow_missing={"type": "bool", "default": False},
repository={"required": True},
src_repo={},
src_is_push={"type": "bool", "default": False},
state={"default": "present"},
tags={"type": "list", "item": "str", "required": True},
),
required_if=[("state", "present", ["src_repo"])],
) as module:
natural_key = {"name": module.params["repository"]}
PulpContainerRepositoryContent(module, natural_key).process()


if __name__ == "__main__":
main()
52 changes: 52 additions & 0 deletions roles/pulp_container_content/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
pulp_container_content
======================

This role adds and removes content in Pulp container repositories.

Currently only supports tags.

Role variables
--------------

* `pulp_url`: URL of Pulp server. Default is `https://localhost:8080`
* `pulp_username`: Username used to access Pulp server. Default is `admin`
* `pulp_password`: Password used to access Pulp server. Default is unset
* `pulp_validate_certs`: Whether to validate certificates. Default is `true`.
* `pulp_container_content`: List of content to add or remove. Each item is a dict with the following keys:

* `allow_missing`: Whether to ignore missing tags in the source repository
when `state` is `present`.
* `repository`: Name of the repository to copy to when `state is `present`
or the repository to remove from when `state` is `absent`.
* `src_repo`: Name of the repository to copy from when `state` is `present`.
* `src_is_push`: Whether `src_repo` is a push repository. Default is `false`.
* `state`: Whether to add (`present`) or remove (`absent`) content.
* `tags`: List of names of tags to add or remove.

Example playbook
----------------

```yaml
---
- name: Add or remove container content
any_errors_fatal: True
gather_facts: True
hosts: all
roles:
- role: pulp_container_content
pulp_username: admin
pulp_password: "{{ secrets_pulp_admin_password }}"
pulp_container_content:
# Copy tag1 and tag2 from repo1 to repo2
- src_repo: repo1
src_is_push: true
repository: repo2
tags:
- tag1
- tag2
# Remove tag3 from repo3
- repository: repo3
tags:
- tag3
state: absent
```
7 changes: 7 additions & 0 deletions roles/pulp_container_content/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
pulp_url: https://localhost:8080
pulp_username: admin
pulp_password:
pulp_validate_certs: true

pulp_container_content: []
14 changes: 14 additions & 0 deletions roles/pulp_container_content/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
- name: Add or remove content units
stackhpc.pulp.pulp_container_content:
pulp_url: "{{ pulp_url }}"
username: "{{ pulp_username }}"
password: "{{ pulp_password }}"
validate_certs: "{{ pulp_validate_certs | bool }}"
allow_missing: "{{ item.allow_missing | default(omit) }}"
src_repo: "{{ item.src_repo | default(omit) }}"
src_is_push: "{{ item.src_is_push | default(omit) }}"
repository: "{{ item.repository }}"
tags: "{{ item.tags }}"
state: "{{ item.state | default(omit) }}"
loop: "{{ pulp_container_content }}"
Loading