Skip to content

Commit

Permalink
Use pulp_glue converge
Browse files Browse the repository at this point in the history
Also bump the glue requirement to 0.28 and rerecord the fixtures with
it.
  • Loading branch information
mdellweg committed Aug 29, 2024
1 parent ad4bf8c commit f90a5c2
Show file tree
Hide file tree
Showing 159 changed files with 518,395 additions and 287,949 deletions.
2 changes: 1 addition & 1 deletion lower_bounds_constraints.lock
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pulp-glue==0.20.0
pulp-glue==0.28.0
8 changes: 7 additions & 1 deletion meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,11 @@ action_groups:
- status
- task
- x509_cert_guard
requires_ansible: '>=2.15.0,<2.18'
plugin_routing:
modules:
file_repository_content:
deprecation:
removal_version: "0.1.0"
warning_text: "Use pulp.squeezer.file_content instead."
requires_ansible: ">=2.15.0,<2.18"
...
122 changes: 62 additions & 60 deletions plugins/module_utils/pulp_glue.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
from packaging.requirements import SpecifierSet
from pulp_glue.common import __version__ as pulp_glue_version
from pulp_glue.common.context import PulpContext, PulpException, PulpNoWait
from pulp_glue.common.openapi import BasicAuthProvider

GLUE_VERSION_SPEC = ">=0.20.0,<0.27"
if not SpecifierSet(GLUE_VERSION_SPEC).contains(pulp_glue_version):
GLUE_VERSION_SPEC = ">=0.28.0,<0.29.0"
if not SpecifierSet(GLUE_VERSION_SPEC, prereleases=True).contains(pulp_glue_version):
raise ImportError(
f"Installed 'pulp-glue' version '{pulp_glue_version}' is not in '{GLUE_VERSION_SPEC}'."
)
Expand Down Expand Up @@ -86,17 +87,11 @@ def __init__(self, **kwargs):
self.fail_json(msg=missing_required_lib(import_error[0]), exception=import_error[1])

auth_args = {}
if SpecifierSet(">=0.24.0").contains(pulp_glue_version):
if self.params["username"]:
from pulp_glue.common.openapi import BasicAuthProvider

auth_args["auth_provider"] = BasicAuthProvider(
username=self.params["username"],
password=self.params["password"],
)
else:
auth_args["username"] = self.params["username"]
auth_args["password"] = self.params["password"]
if self.params["username"]:
auth_args["auth_provider"] = BasicAuthProvider(
username=self.params["username"],
password=self.params["password"],
)

self.pulp_ctx = PulpSqueezerContext(
api_root="/pulp/",
Expand All @@ -106,22 +101,28 @@ def __init__(self, **kwargs):
key=self.params["user_key"],
validate_certs=self.params["validate_certs"],
refresh_cache=self.params["refresh_api_cache"],
safe_calls_only=self.check_mode,
user_agent=f"Squeezer/{__VERSION__}",
**auth_args,
),
background_tasks=False,
timeout=self.params["timeout"],
fake_mode=self.check_mode, # This sets api_kwargs["safe_calls_only"] for us.
)

def __enter__(self):
self._changed = False
self._results = {}
self._diff_states = []

return self

def __exit__(self, exc_class, exc_value, tb):
if exc_class is None:
if self._diff_states:
self._results["diff"] = {
"before": self._diff_states[0],
"after": self._diff_states[-1],
}
self.exit_json(changed=self._changed, **self._results)
else:
if issubclass(exc_class, (PulpException, PulpNoWait, SqueezerException)):
Expand All @@ -141,6 +142,9 @@ def set_changed(self):
def set_result(self, key, value):
self._results[key] = value

def record_diff_state(self, value):
self._diff_states.append(value)


class PulpEntityAnsibleModule(PulpAnsibleModule):
def __init__(self, context_class, entity_singular, entity_plural, **kwargs):
Expand All @@ -152,6 +156,7 @@ def __init__(self, context_class, entity_singular, entity_plural, **kwargs):
argument_spec.update(kwargs.pop("argument_spec", {}))
super().__init__(argument_spec=argument_spec, **kwargs)
self.state = self.params["state"]

self.context = context_class(self.pulp_ctx)
self.entity_singular = entity_singular
self.entity_plural = entity_plural
Expand All @@ -162,59 +167,56 @@ def represent(self, entity):
for key, value in entity.items()
}

def process(self, natural_key, desired_attributes):
if None not in natural_key.values():
if "pulp_href" in natural_key:
self.context.pulp_href = natural_key["pulp_href"]
else:
self.context.entity = natural_key
try:
entity = self.represent(self.context.entity)
except PulpException:
entity = None
if self.state is None:
pass
elif self.state == "absent":
if entity is not None:
if not self.check_mode:
self.context.delete()
entity = None
self.set_changed()
elif self.state == "present":
entity = self.process_present(entity, natural_key, desired_attributes)
else:
entity = self.process_special(entity, natural_key, desired_attributes)
self.set_result(self.entity_singular, entity)
def process(self, natural_key, desired_attributes, defaults=None):
if self.state is None:
return self.process_info(natural_key, desired_attributes)

if "pulp_href" in natural_key:
self.context.pulp_href = natural_key["pulp_href"]
else:
if None in natural_key.values():
raise SqueezerException("Insufficient information to identify the entity.")
self.context.entity = natural_key

if self.state == "present":
desired_entity = desired_attributes
elif self.state == "absent":
desired_entity = None
else:
if self.state is not None:
raise SqueezerException(f"Invalid state '{self.state}' for entity listing.")
self.set_result(
self.entity_singular,
self.process_special(desired_attributes, defaults=defaults),
)
return
changed, before, after = self.context.converge(desired_entity, defaults=defaults)
if before is not None:
before = self.represent(before)
if after is not None:
after = self.represent(after)
if changed:
self.set_changed()
self.record_diff_state(before)
self.record_diff_state(after)
self.set_result(self.entity_singular, after)

def process_info(self, natural_key, desired_attributes):
if any((value is not None for value in desired_attributes.values())):
raise SqueezerException("Cannot use attributes when querying entities.")
# TODO turn this into a filtering query instead
if None in natural_key.values():
entities = [
self.represent(entity)
for entity in self.context.list(limit=-1, offset=0, parameters={})
]
self.set_result(self.entity_plural, entities)

def process_present(self, entity, natural_key, desired_attributes):
if entity is None:
entity = {**desired_attributes, **natural_key}
if not self.check_mode:
self.context.create(body=entity)
entity = self.context.entity
entity = self.represent(entity)
self.set_changed()
else:
updated_attributes = {k: v for k, v in desired_attributes.items() if entity.get(k) != v}
if updated_attributes:
if not self.check_mode:
self.context.update(body=updated_attributes)
entity = self.context.entity
else:
entity.update(updated_attributes)
entity = self.represent(entity)
self.set_changed()
return entity

def process_special(self, entity, natural_key, desired_attributes):
if "pulp_href" in natural_key:
self.context.pulp_href = natural_key["pulp_href"]
else:
self.context.entity = natural_key
self.set_result(self.entity_singular, self.represent(self.context.entity))

def process_special(self, entity, natural_key, desired_attributes, defaults=None):
raise SqueezerException(f"Invalid state '{self.state}'.")


Expand Down
66 changes: 48 additions & 18 deletions plugins/modules/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,56 @@
)

try:
from pulp_glue.core.context import PulpArtifactContext
from pulp_glue.common.context import PulpEntityNotFound
from pulp_glue.core.context import PulpArtifactContext as _PulpArtifactContext

PULP_CLI_IMPORT_ERR = None

# Patch the Context to make converge call upload
# It's a case study at this point. Eventually glue should handle this.
class PulpArtifactContext(_PulpArtifactContext):
def converge(self, desired_attributes, defaults=None):
"""
Converge an entity to have a set of desired attributes.
This will look for the entity, and depending on what it found and what should be, create,
delete or update the entity.
Parameters:
desired_attributes: Dictionary of attributes the entity should have.
Returns:
Tuple of (changed, before, after)
"""
try:
entity = self.entity
except PulpEntityNotFound:
entity = None

if desired_attributes is None:
if entity is not None:
# raise SqueezerException("Artifacts cannot be deleted")
self.delete()
return True, entity, None
else:
if entity is None:
# This is being quite different:
with open(defaults["file"], "rb") as file:
self.upload(
file=file,
chunk_size=defaults["chunk_size"],
sha256=self._entity_lookup["sha256"],
)
return True, None, self.entity
return False, entity, entity

except ImportError:
PULP_CLI_IMPORT_ERR = traceback.format_exc()
PulpArtifactContext = None


class PulpArtifactAnsibleModule(PulpEntityAnsibleModule):
def process_present(self, entity, natural_key, desired_attributes):
if entity is None:
if self.check_mode:
entity = {**desired_attributes, **natural_key}
else:
with open(self.params["file"], "rb") as infile:
self.context.upload(
infile, sha256=natural_key["sha256"], chunk_size=self.params["chunk_size"]
)
entity = self.context.entity
self.set_changed()
return self.represent(entity)


def main():
with PulpArtifactAnsibleModule(
with PulpEntityAnsibleModule(
context_class=PulpArtifactContext,
entity_singular="artifact",
entity_plural="artifacts",
Expand Down Expand Up @@ -144,8 +169,13 @@ def main():
natural_key = {
"sha256": sha256,
}
desired_attributes = {}
defaults = {
"file": module.params["file"],
"chunk_size": module.params["chunk_size"],
}

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


if __name__ == "__main__":
Expand Down
58 changes: 52 additions & 6 deletions plugins/modules/file_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
description:
- Relative path of the file content unit
type: str
file:
description:
- A path to a file tobe uploaded as the new content unit.
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.glue
Expand Down Expand Up @@ -62,14 +75,19 @@
"""


import os
import traceback

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

try:
from pulp_glue.file.context import PulpFileContentContext
from pulp_glue.file.context import PulpFileContentContext, PulpFileRepositoryContext

PULP_CLI_IMPORT_ERR = None

except ImportError:
PULP_CLI_IMPORT_ERR = traceback.format_exc()
PulpFileContentContext = None
Expand All @@ -84,19 +102,47 @@ def main():
argument_spec={
"sha256": {"aliases": ["digest"]},
"relative_path": {},
"file": {"type": "path"},
"chunk_size": {"type": "int", "default": 33554432},
"repository": {},
},
required_if=[
("state", "present", ["sha256", "relative_path"]),
("state", "absent", ["sha256", "relative_path"]),
("state", "present", ["file", "relative_path", "repository"]),
("state", "absent", ["relative_path", "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": module.params["sha256"],
"sha256": sha256,
"relative_path": module.params["relative_path"],
}
desired_attributes = {}
defaults = {
"file": module.params["file"],
"chunk_size": module.params["chunk_size"],
}

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

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


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit f90a5c2

Please sign in to comment.