Skip to content

Commit

Permalink
Creates basic pulp.plugin package
Browse files Browse the repository at this point in the history
This PR adds the following base objects as part of
the plugin API.

* Cataloger
* Importer
* Profiler
* Publisher

It also imports the following objects from
pulp.platform.models for usage by plugins:

* ProgressBar
* ProgressSpinner
* Repository
* RepositoryContent

It removes several modules from the old pulp.plugins
package.

closes #2181
https://pulp.plan.io/issues/2181
  • Loading branch information
Brian Bouterse committed Sep 12, 2016
1 parent d7cc916 commit 06ed427
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 1,315 deletions.
2 changes: 2 additions & 0 deletions plugin/pulp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
6 changes: 6 additions & 0 deletions plugin/pulp/plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pulp.platform.models import ProgressBar, ProgressSpinner, Repository, RepositoryContent

from .cataloger import Cataloger
from .publisher import Publisher
from .importer import Importer
from .profiler import Profiler
48 changes: 48 additions & 0 deletions plugin/pulp/plugin/cataloger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class Cataloger(object):
"""
The base cataloger to index content sources.
This is meant to be subclassed by plugin authors to given the plugin control where content is
fetched from. For a given url the plugin should return a
:class: `~nectar.downloaders.base.Downloader` object. Using this interface, content that is
stored locally or in multiple locations can be fetched more efficiently.
The platform will use one :class: `~pulp.plugin.Cataloger` instance per content source so this
object only needs to be concerned with indexing a single source provided in the config.
:ivar config: The content source configuration
:type config: dict
"""

def __init__(self, config):
"""
Initialize the Cataloger with a config.
:param config: The content source configuration.
:type config: dict
"""
self.config = config

def get_downloader(self, url):
"""
Get a :class: `~nectar.downloaders.base.Downloader` suitable for downloading content at url
This allows the plugin author to control where content is fetched from.
:param url: The URL for the content source.
:type url: str
:return: A configured downloader.
:rtype: :class: `nectar.downloaders.base.Downloader`
"""
raise NotImplementedError()

def refresh(self):
"""
Refresh the content catalog.
This should cause the plugin to refresh the content catalog to look for new content and/or
verify the existence of known content. The extent of the feature set provided with refresh
by the plugin is up to the plugin author.
"""
raise NotImplementedError()
70 changes: 70 additions & 0 deletions plugin/pulp/plugin/importer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from pulp.platform.models import Importer as PlatformImporter


class Importer(PlatformImporter):
"""
The base importer object to sync content.
This is meant to be subclassed by plugin authors as an opportunity to provide:
* Plugin specific sync functionality
* Add persistent data attributes for a plugin importer subclass
* Additional validation of plugin importer subclass configuration
The sync implementation is provided by :meth: `Importer.sync` which provides more details.
Failing to implement this method will prevent sync functionality for this plugin type.
This object is a Django model that inherits from :class: `pulp.platform.models.Importer` which
provides the platform persistent attributes for an importer object. Plugin authors can add
additional persistent importer data by subclassing this object and adding Django fields. We
defer to the Django docs on extending this model definition with additional fields.
Validation is done the Django way, so custom validation can also be added the same as any
Django model. We defer to the Django docs on adding custom validation to the subclassed
importer. If any of the model validation methods are overridden, be sure to call super() so the
platform can still perform its validation.
Instantiation and calling of the subclassed plugin Importer is described in detail in the
:meth: `Importer.sync` method.
"""

def sync(self):
"""
Perform a sync
It is expected that plugins wanting to support sync will provide an implementation on the
subclassed Importer.
The model attributes encapsulate all of the information required to sync. This includes the
platform :class: `pulp.platform.models.Importer` base attributes and any custom attributes
defined by the subclass.
The model attributes were loaded from the database and then had the user specified override
config applied on top. Additionally the importer is read-only and prevents the saving of
changes to the Importer instance.
Instantiation and calling of the sync method by the platform is roughly done with the
following:
1. The plugin provides an implementation called WidgetImporter which subclasses Importer
2. The user makes a call to sync widget_importer (say id=10) with some override config
3. The platform loads the saved
>>> wi = WidgetImporter.objects.get(id=10)
4. The platform puts the WidgetImporter into read-only mode
5. The override config values are written over the in memory WidgetImporter
6. Call the full_clean() method on the Django model for validation
>>> wi.full_clean()
7. Call into the sync method
>>> wi.sync()
Subclasses are designed to override this default implementation and should not call super().
"""
raise NotImplementedError()
42 changes: 42 additions & 0 deletions plugin/pulp/plugin/profiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Profiler(object):
"""
The base profiler class to answer applicability questions regarding updates.
This is meant to be subclassed by plugin authors who wish to provide the applicability
feature set. The plugin implementation returns a list of plugin subclassed
:class: `~pulp.plugin.ContentUnit` objects. Those objects are in the repo and are applicable
for the unit_profile.
See :meth: `Profiler.calculate_applicable_units` for more info.
:ivar repo: The repository to be used to calculate applicability against the given
consumer profile.
:type repo: :class: `pulp.plugin.Repository`
"""

def __init__(self, repo):
"""
Initialize with a :class: `pulp.plugin.Repository` object
:param repo: The repository to be used to calculate applicability against the given
consumer profile.
:type repo: :class: `pulp.plugin.Repository`
"""
self.repo = repo

def calculate_applicable_units(self, unit_profile):
"""
Return the applicable units for unit_profile
Calculate and return a list of subclasses of :class: `~pulp.plugin.ContentUnit`
applicable to consumers with given 'unit_profile'. Applicability is calculated against all
content units belonging to the associated repository. The definition of "applicable" is
content type specific and up to the subclassed implementation.
:param unit_profile: The consumer unit profile
:type unit_profile: dict
:return: a list of applicable :class: `~pulp.plugin.ContentUnit` objects
:rtype: list of :class: `~pulp.plugin.ContentUnit` objects
"""
raise NotImplementedError()
73 changes: 73 additions & 0 deletions plugin/pulp/plugin/publisher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from pulp.platform.models import Publisher as PlatformPublisher


class Publisher(PlatformPublisher):
"""
The base Publisher object to publish content
This is meant to be subclassed by plugin authors as an opportunity to provide:
* Plugin specific publish functionality
* Add persistent data attributes for a plugin publisher subclass
* Additional validation of plugin publisher subclass configuration
The publish implementation is provided by :meth: `Publisher.publish` which provides more
details. Failing to implement this method will prevent publish functionality for this plugin
type.
This object is a Django model that inherits from :class: `pulp.platform.models.Publisher`
which provides the platform persistent attributes for a publisher object. Plugin authors can
add additional persistent publisher data by subclassing this object and adding Django
fields. We defer to the Django docs on extending this model definition with additional fields.
Validation is done the Django way, so custom validation can also be added the same as any
Django model. We defer to the Django docs on adding custom validation to the subclassed
publisher. If any of the model validation methods are overridden, be sure to call super() so
the platform can still perform its validation.
Instantiation and calling of the subclassed plugin Publisher is described in detail in the
:meth: `Publisher.publish` method.
"""

def publish(self):
"""
Perform a publish
It is expected that plugins wanting to support publish will provide an implementation on the
subclassed Publisher.
The model attributes encapsulate all of the information required to publish. This includes
the platform :class: `pulp.platform.models.Publish` base attributes and any custom
attributes defined by the subclass.
The model attributes were loaded from the database and then had the user specified override
config applied on top. Additionally the publisher is read-only and prevents the saving of
changes to the Publisher instance.
Instantiation and calling of the publish method by the platform is roughly done with the
following:
1. The plugin provides an implementation called WidgetPublisher which subclasses
Publisher
2. The user makes a call to publish widget_publisher (say id=10) with some override
config
3. The platform loads the saved
>>> wd = WidgetPublisher.objects.get(id=10)
4. The platform puts the WidgetPublisher into read-only mode
5. The override config values are written over the in memory WidgetPublisher
6. Call the full_clean() method on the Django model for validation
>>> wd.full_clean()
7. Call into the publish method
>>> wd.publish()
Subclasses are designed to override this default implementation and should not call super().
"""
raise NotImplementedError()
13 changes: 13 additions & 0 deletions plugin/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from setuptools import setup, find_packages

requirements = []

setup(
name='pulp-plugin',
version='3.0a1',
license='GPLv2+',
packages=find_packages(exclude=['test']),
author='Pulp Team',
author_email='pulp-list@redhat.com',
install_requires=requirements,
)
43 changes: 0 additions & 43 deletions server/pulp/plugins/cataloger.py

This file was deleted.

Loading

0 comments on commit 06ed427

Please sign in to comment.