Source code for cfme.services.catalogs.catalog_items.ansible_catalog_items
import attr
from navmazing import NavigateToAttribute, NavigateToSibling
from widgetastic.utils import (Parameter, ParametrizedLocator, ParametrizedString, Version,
VersionPick)
from widgetastic.widget import Checkbox, Table, Text, View
from widgetastic_manageiq import FileInput, SummaryForm, SummaryTable
from widgetastic_patternfly import (
BootstrapSelect as VanillaBootstrapSelect,
BootstrapSwitch,
Button,
Input,
Tab
)
from cfme.services.catalogs import ServicesCatalogView
from cfme.utils.appliance.implementations.ui import CFMENavigateStep, navigator
from . import BaseCatalogItem
[docs]class BootstrapSelect(VanillaBootstrapSelect):
"""BootstrapSelect widget for Ansible Playbook Catalog Item form.
BootstrapSelect widgets don't have `data-id` attribute in this form, so we have to override ROOT
locator.
"""
ROOT = ParametrizedLocator('.//select[normalize-space(@name)={@id|quote}]/..')
[docs] def fill(self, value):
# Some BootstrapSelects appears on the page only if another select changed. Therefore we
# should wait until it appears and only then we can fill it.
self.wait_displayed()
super(BootstrapSelect, self).fill(value)
[docs]class ActionsCell(View):
edit = Button(
**{"ng-click": ParametrizedString(
"vm.editKeyValue('{@tab}', this.key, this.key_value, $index)")}
)
delete = Button(
**{"ng-click": ParametrizedString(
"vm.removeKeyValue('{@tab}', this.key, this.key_value, $index)")}
)
def __init__(self, parent, tab, logger=None):
View.__init__(self, parent, logger=logger)
self.tab = parent.parent.parent.parent.tab
[docs]class AnsibleExtraVariables(View):
"""Represents extra variables part of ansible service catalog edit form.
Args:
tab (str): tab name where this view is located. Can be "provisioning" or "retirement".
"""
variable = Input(name=ParametrizedString("{@tab}_key"))
default_value = Input(name=ParametrizedString("{@tab}_value"))
add = Button(**{"ng-click": ParametrizedString("vm.addKeyValue('{@tab}')")})
variables_table = Table(
".//div[@id='variables_div']//table",
column_widgets={"Actions": ActionsCell(tab=Parameter("@tab"))}
)
def __init__(self, parent, tab, logger=None):
View.__init__(self, parent, logger=logger)
self.tab = tab
def _values_to_remove(self, values):
return list(set(self.all_vars) - set(values))
def _values_to_add(self, values):
return list(set(values) - set(self.all_vars))
[docs] def fill(self, values):
"""
Args:
values (list): [] to remove all vars or [("var", "value"), ...] to fill the view.
"""
if set(values) == set(self.all_vars):
return False
else:
for value in self._values_to_remove(values):
rows = list(self.variables_table)
for row in rows:
if row[0].text == value[0]:
row["Actions"].widget.delete.click()
break
for value in self._values_to_add(values):
self.variable.fill(value[0])
self.default_value.fill(value[1])
self.add.click()
return True
@property
def all_vars(self):
if self.variables_table.is_displayed:
return [(row["Variable"].text, row["Default value"].text) for
row in self.variables_table]
else:
return []
[docs]class AnsibleCatalogItemForm(ServicesCatalogView):
title = Text(".//span[@id='explorer_title_text']")
name = Input("name")
description = Input("description")
display_in_catalog = BootstrapSwitch(name="display")
catalog = BootstrapSelect("catalog_id")
@View.nested
class provisioning(Tab): # noqa
repository = BootstrapSelect("provisioning_repository_id")
playbook = BootstrapSelect("provisioning_playbook_id")
machine_credential = BootstrapSelect("provisioning_machine_credential_id")
cloud_type = BootstrapSelect("provisioning_cloud_type")
cloud_credential = BootstrapSelect("provisioning_cloud_credential_id")
localhost = Input(id="provisioning_inventory_localhost")
specify_host_values = Input(id="provisioning_inventory_specify")
hosts = Input("provisioning_inventory")
logging_output = BootstrapSelect("provisioning_log_output")
max_ttl = Input("provisioning_execution_ttl")
escalate_privilege = BootstrapSwitch("provisioning_become_enabled")
verbosity = BootstrapSelect("provisioning_verbosity")
use_exisiting = Checkbox(locator=".//label[normalize-space(.)='Use Existing']/input")
create_new = Checkbox(locator=".//label[normalize-space(.)='Create New']/input")
provisioning_dialog_id = BootstrapSelect("provisioning_dialog_id")
provisioning_dialog_name = Input(name="vm.provisioning_dialog_name")
extra_vars = AnsibleExtraVariables(tab="provisioning")
@View.nested
class retirement(Tab): # noqa
# TODO Somehow need to handle a modal window
copy_from_provisioning = Button("Copy from provisioning")
repository = BootstrapSelect("retirement_repository_id")
playbook = BootstrapSelect("retirement_playbook_id")
machine_credential = BootstrapSelect("retirement_machine_credential_id")
cloud_type = BootstrapSelect("retirement_cloud_type")
cloud_credential = BootstrapSelect("retirement_cloud_credential_id")
localhost = Input(id="retirement_inventory_localhost")
specify_host_values = Input(id="retirement_inventory_specify")
hosts = Input("retirement_inventory")
logging_output = BootstrapSelect("retirement_log_output")
max_ttl = Input("retirement_execution_ttl")
escalate_privilege = BootstrapSwitch("retirement_become_enabled")
verbosity = BootstrapSelect("retirement_verbosity")
remove_resources = VersionPick({
Version.lowest(): BootstrapSelect("vm.catalogItemModel.retirement_remove_resources"),
"5.9": BootstrapSelect("vm.vm.catalogItemModel.retirement_remove_resources")
})
extra_vars = AnsibleExtraVariables(tab="retirement")
cancel = Button("Cancel")
[docs]class AddAnsibleCatalogItemView(AnsibleCatalogItemForm):
add = Button("Add")
@property
def is_displayed(self):
return False
[docs]class EditAnsibleCatalogItemView(AnsibleCatalogItemForm):
save = Button("Save")
reset = Button("Reset")
@property
def is_displayed(self):
return False
[docs]class DetailsEntitiesAnsibleCatalogItemView(View):
title = Text(".//span[@id='explorer_title_text']")
basic_information = SummaryForm("Basic Information")
custom_image = FileInput("upload_image")
upload = Button("Upload")
smart_management = SummaryTable("Smart Management")
@View.nested
class provisioning(Tab): # noqa
info = SummaryForm("Provisioning Info")
variables_and_default_values = Table(".//div[@id='provisioning']//table")
@View.nested
class retirement(Tab): # noqa
info = SummaryForm("Retirement Info")
variables_and_default_values = Table(".//div[@id='retirement']//table")
[docs]class DetailsAnsibleCatalogItemView(ServicesCatalogView):
"""Has to be in view standards, changed for Taggable.get_tags()"""
entities = View.nested(DetailsEntitiesAnsibleCatalogItemView)
@property
def is_displayed(self):
return (
self.in_explorer and
self.entities.title.text == 'Service Catalog Item "{}"'.format(
self.context["object"].name
)
)
@attr.s
[docs]class AnsiblePlaybookCatalogItem(BaseCatalogItem):
"""Represents Ansible Playbook catalog item.
Example:
.. code-block:: python
collection = appliance.collections.catalog_items
catalog_item = collection.create(
collection.ANSIBLE_PLAYBOOK
"some_catalog_name",
"some_description",
provisioning={
"repository": "Some repository",
"playbook": "some_playbook.yml",
"machine_credential": "CFME Default Credential",
"create_new": True,
"provisioning_dialog_name": "some_dialog",
"extra_vars": [("some_var", "some_value")]
}
)
catalog_item.delete()
Args:
name (str): catalog item name
description (str): catalog item description
provisioning (dict): provisioning data
catalog (py:class:`cfme.services.catalogs.catalog.Catalog`): catalog object
display_in_catalog (bool): whether this playbook displayed in catalog
retirement (dict): retirement data
"""
name = attr.ib()
description = attr.ib()
provisioning = attr.ib()
catalog = attr.ib(default=None)
display_in_catalog = attr.ib(default=None)
retirement = attr.ib(default=None)
item_type = "Ansible Playbook"
@property
def fill_dict(self):
return {
"name": self.name,
"description": self.description,
"display_in_catalog": self.display_in_catalog,
"catalog": getattr(self.catalog, "name", None),
"provisioning": self.provisioning,
"retirement": self.retirement
}
@navigator.register(AnsiblePlaybookCatalogItem, "Add")
[docs]class Add(CFMENavigateStep):
VIEW = AddAnsibleCatalogItemView
prerequisite = NavigateToAttribute("parent", "Choose Type")
[docs] def step(self):
self.prerequisite_view.select_item_type.select_by_visible_text(self.obj.item_type)
@navigator.register(AnsiblePlaybookCatalogItem, "Edit")
[docs]class Edit(CFMENavigateStep):
VIEW = EditAnsibleCatalogItemView
prerequisite = NavigateToSibling("Details")
@navigator.register(AnsiblePlaybookCatalogItem, "Details")
[docs]class Details(CFMENavigateStep):
VIEW = DetailsAnsibleCatalogItemView
prerequisite = NavigateToAttribute("parent", "All")
[docs] def step(self):
tree = self.prerequisite_view.catalog_items.tree
tree.click_path(
"All Catalog Items",
getattr(self.obj.catalog, "name", "Unassigned"),
self.obj.name
)