aboutsummaryrefslogtreecommitdiffstats
path: root/src/workflow
diff options
context:
space:
mode:
Diffstat (limited to 'src/workflow')
-rw-r--r--src/workflow/README31
-rw-r--r--src/workflow/forms.py10
-rw-r--r--src/workflow/models.py23
-rw-r--r--src/workflow/resource_bundle_workflow.py3
-rw-r--r--src/workflow/sw_bundle_workflow.py2
-rw-r--r--src/workflow/tests/test_steps.py15
-rw-r--r--src/workflow/tests/test_workflows.py4
7 files changed, 75 insertions, 13 deletions
diff --git a/src/workflow/README b/src/workflow/README
new file mode 100644
index 0000000..fb4b949
--- /dev/null
+++ b/src/workflow/README
@@ -0,0 +1,31 @@
+This app creates "workflows", which are long and complex interactions from the user.
+Workflows are composed of multiple steps. At each step the user inputs some information.
+The content of one step may impact following steps.
+
+The WorkflowStep object is the abstract type for all the workflow steps.
+Important attributes and methods:
+
+template - the django template to use when rendering this step
+valid - the status code from WorkflowStepStatus
+
+get_context() - returns a dictionary that is used when rendering this step's template
+ You should always call super's get_context and add / overwrite any data into that
+ dictionary
+
+post(data, user) - this method is called when the step is POST'd to.
+ data is from the request object, suitable for a Form's constructor
+
+
+Repository
+Each step has a reference to a shared repository (self.repo).
+The repo is a key-value store that allows the steps to share data
+
+Steps render based on the current state of the repo. For example, a step
+may get information about each host the user said they want and ask for additional
+input for each machine.
+Because the steps render based on what is in the repo, a user can easily go back to
+a previous step and change some data. This data will change in the repo and
+affect later steps accordingly.
+
+Everything stored in the repo is temporary. After a workflow has been completed, the repo
+is translated into Django models and saved to the database.
diff --git a/src/workflow/forms.py b/src/workflow/forms.py
index 4d5e9e2..f7a20eb 100644
--- a/src/workflow/forms.py
+++ b/src/workflow/forms.py
@@ -65,7 +65,9 @@ class SearchableSelectMultipleField(forms.Field):
items=None, queryset=None, show_from_noentry=True, show_x_results=-1,
results_scrollable=False, selectable_limit=-1, placeholder="search here",
name="searchable_select", initial=[], **kwargs):
- """from the documentation:
+ """
+ From the documentation.
+
# required -- Boolean that specifies whether the field is required.
# True by default.
# widget -- A Widget class, or instance of a Widget class, that should
@@ -90,7 +92,6 @@ class SearchableSelectMultipleField(forms.Field):
# label_suffix -- Suffix to be added to the label. Overrides
# form's label_suffix.
"""
-
self.widget = widget
if self.widget is None:
self.widget = SearchableSelectMultipleWidget(
@@ -287,8 +288,9 @@ class FormUtils:
@staticmethod
def getLabData(multiple_hosts=False):
"""
- Gets all labs and thier host profiles and returns a serialized version the form can understand.
- Should be rewritten with a related query to make it faster
+ Get all labs and thier host profiles, returns a serialized version the form can understand.
+
+ Could be rewritten with a related query to make it faster
"""
# javascript truthy variables
true = 1
diff --git a/src/workflow/models.py b/src/workflow/models.py
index 99608f6..32ac39c 100644
--- a/src/workflow/models.py
+++ b/src/workflow/models.py
@@ -26,6 +26,15 @@ from booking.models import Booking
class BookingAuthManager():
+ """
+ Verifies Booking Authorization.
+
+ Class to verify that the user is allowed to book the requested resource
+ The user must input a url to the INFO.yaml file to prove that they are the ptl of
+ an approved project if they are booking a multi-node pod.
+ This class parses the url and checks the logged in user against the info file.
+ """
+
LFN_PROJECTS = ["opnfv"] # TODO
def parse_github_url(self, url):
@@ -124,7 +133,9 @@ class BookingAuthManager():
def parse_url(self, info_url):
"""
- will return the PTL in the INFO file on success, or None
+ Parse the project URL.
+
+ Gets the INFO.yaml file from the project and returns the PTL info.
"""
if "github" in info_url:
return self.parse_github_url(info_url)
@@ -137,6 +148,8 @@ class BookingAuthManager():
def booking_allowed(self, booking, repo):
"""
+ Assert the current Booking Policy.
+
This is the method that will have to change whenever the booking policy changes in the Infra
group / LFN. This is a nice isolation of that administration crap
currently checks if the booking uses multiple servers. if it does, then the owner must be a PTL,
@@ -158,6 +171,14 @@ class BookingAuthManager():
class WorkflowStepStatus(object):
+ """
+ Poor man's enum for the status of a workflow step.
+
+ The steps in a workflow are not completed (UNTOUCHED)
+ or they have been completed correctly (VALID) or they were filled out
+ incorrectly (INVALID)
+ """
+
UNTOUCHED = 0
INVALID = 100
VALID = 200
diff --git a/src/workflow/resource_bundle_workflow.py b/src/workflow/resource_bundle_workflow.py
index 2f4aa5d..f57476b 100644
--- a/src/workflow/resource_bundle_workflow.py
+++ b/src/workflow/resource_bundle_workflow.py
@@ -253,12 +253,13 @@ class Define_Nets(WorkflowStep):
def decomposeXml(self, xmlString):
"""
+ Translate XML into useable data.
+
This function takes in an xml doc from our front end
and returns dictionaries that map cellIds to the xml
nodes themselves. There is no unpacking of the
xml objects, just grouping and organizing
"""
-
connections = {}
networks = {}
hosts = {}
diff --git a/src/workflow/sw_bundle_workflow.py b/src/workflow/sw_bundle_workflow.py
index 4dc0b8e..ebd8c86 100644
--- a/src/workflow/sw_bundle_workflow.py
+++ b/src/workflow/sw_bundle_workflow.py
@@ -28,6 +28,8 @@ class Define_Software(WorkflowStep):
def build_filter_data(self, hosts_data):
"""
+ Build list of Images to filter out.
+
returns a 2D array of images to exclude
based on the ordering of the passed
hosts_data
diff --git a/src/workflow/tests/test_steps.py b/src/workflow/tests/test_steps.py
index 39b1f86..6101d4f 100644
--- a/src/workflow/tests/test_steps.py
+++ b/src/workflow/tests/test_steps.py
@@ -8,7 +8,8 @@
##############################################################################
"""
-This file tests basic functionality of each step class
+This file tests basic functionality of each step class.
+
More in depth case coverage of WorkflowStep.post() must happen elsewhere.
"""
@@ -28,9 +29,11 @@ from workflow.tests import test_fixtures
class TestConfig:
"""
- Basic class to instantiate and hold reference
+ Basic class to instantiate and hold reference.
+
to models we will need often
"""
+
def __init__(self, usr=None):
self.lab = make_lab()
self.user = usr or make_user()
@@ -77,6 +80,8 @@ class StepTestCase(TestCase):
def assertCorrectPostBehavior(self, post_data):
"""
+ Stub for validating step behavior on POST request.
+
allows subclasses to override and make assertions about
the side effects of self.step.post()
post_data is the data passed into post()
@@ -85,6 +90,8 @@ class StepTestCase(TestCase):
def add_to_repo(self, repo):
"""
+ Stub for modifying the step's repo.
+
This method is a hook that allows subclasses to modify
the contents of the repo before the step is created.
"""
@@ -92,8 +99,8 @@ class StepTestCase(TestCase):
def assertValidHtml(self, html_str):
"""
- This method should make sure that html_str is a valid
- html fragment.
+ Assert that html_str is a valid html fragment.
+
However, I know of no good way of doing this in python
"""
self.assertTrue(isinstance(html_str, str))
diff --git a/src/workflow/tests/test_workflows.py b/src/workflow/tests/test_workflows.py
index 293e43d..995d699 100644
--- a/src/workflow/tests/test_workflows.py
+++ b/src/workflow/tests/test_workflows.py
@@ -50,9 +50,7 @@ class WorkflowTestCase(TestCase):
session.save()
def render_steps(self):
- """
- retrieves each step individually at /wf/workflow/step=<index>
- """
+ """Retrieve each step individually at /wf/workflow/step=<index>."""
for i in range(self.step_count):
# renders the step itself, not in an iframe
exception = None