Angular registry of Actions and Views

Registered by Matt Borland

Summary
-------------

This blueprint establishes features useful for the modularization and extensibility of Horizon actions and views, largely through use of a registry.

Motivation
--------------

1) To provide standardization of views and actions so they can be developed and deployed consistently
2) To ensure that view and action features are reasonably "extensible" by third-parties
3) To ensure that views and actions may be easily repurposed--not just work in a single context
4) To provide a single way for developers to easily achieve the above via an application-level registry

60-second overview: https://youtu.be/nBpZebKSWiE

Description / Background
--------------------------------

In Mitaka, we started to address "extensibility" features in Angular. This term is meant to encompass the ability for a Horizon installation to be easily configured to provide more (or less) features without the use of changing source code. For example, if a details display has tabs, it should be easy for a third party to, in their installation or as a plugin, provide additional tabs without altering the Horizon source code. In Mitaka this was partly achieved through the introduction of an "extensibility service" which provided a generic way to manipulate lists (append, remove, replace, etc.) of features. However, there was no framework that used the service automatically, so it was up to the developers of controllers/directives/markup to know to apply the service, and similarly for third-party developers to inspect the code deeply to know how to extend the lists. In short, there was no central place developers could go to in order to find where/how to insert their new functionality.

There is also an interest in making the features of Horizon modular in the sense that common components, such as user actions or views, could be repurposed so they may be easily configured, tested, deployed, and extended. For example, if we are show user actions on both a list page and a details page, we would want that component to be modular in the sense that the actions make no assumptions about their environment, but instead are passed in a standard set of information, and complete in such a way that any view (e.g. a listing or a details view) can react appropriately for its context. If a user deletes an Instance (an action), the context of that action may react differently: a listing may choose to remove a row, or reload the whole list; a detail of that instance may instead want to present a page indicating the old deleted record. The whole point is that actions should not be coded to work only in a single context, and similarly the contexts in which they are created must be able to accept the completion of actions they do not know about. If a third-party builds a new action outside of core Horizon, the developer would like to know that the context (controller, etc.) that calls their action can reasonably react to it even if it.

Additionally, as we move into a transitionary period where we see the development of new views within Horizon, such as the Searchlight panel, we want to ensure that all views and actions we create are usable in these different presentations.

Description / Solution
---------------------------

A common solution to the kinds of problems stated above is to establish a registry. A registry is an application-level service that collects information that can be accessed throughout the application. The value of a registry is that it provides structure to both the creation and extraction of information.

In this particular case, a primary purpose of a registry is to organize data that is common between resource types. A "resource type" means a distinct kind of entity known to OpenStack; for example, a Server or an Image. Each of these kinds of data contains common information, such as names ("Server," "Servers"), actions ("Edit Image," "Launch Instance"), and views (details views, drawer views in a table). These resource types may be identified by their Heat template identifier, e.g. "OS::Nova::Server" for servers/instances. Also, many of these features, such as actions and views, are the exact kinds of things that we want to be extensible. We want third-parties to easily add actions and views, so having a registry that is aware of these actions and views and automatically applies the extensibility service to them is beneficial to these developers.

Description / Implementation
---------------------------------------

The steps to achieving this goal have already been started on in Mitaka. The registry concept was introduced as a way of presenting actions. However, there are specific features that need to be adopted to ensure we meet our goals above:

1) Actions separate themselves from any assumptions of scope and context. They assume they are passed one or more items, from which they should only use a minimum of context (e.g. their ID) to operate upon. For example, editing an object should not edit an existing model but instead a model loaded from the API, even if more expensive than reading a scoped object). To meet this implementation, existing actions must not interact with scoped items or manipulate the item they are passed.

2) Actions return promises that, when resolved, provide a standardized set of data. This allows any context can use to understand roughly what has occurred as a result of the action. In this case, an object that provides the following is required:
 { updated: [{type: "OS::Glance::Image", id: "1d202d9e-121b-11e6-bab5-080027749b58"}],
   created: [],
   deleted: [],
   failed: [] }

The objects in each list must conform to having member 'type' as a Heat name for the resource type affected, and 'id' as the serialized identifier for the object. In most cases the ID will be simply the string of the ID, however, some items may require a different reference, for example, a path for a Swift object. An action-result service should be established that provides convenient methods for both generating and interpreting these promise resolutions.

Multiple objects of any category (e.g. 'deleted,' 'failed') are allowed, and they may be of any type. For example, the result of launching an instance may have created both an instance but also a key pair; deleting images may have affected multiple images; creating a snapshot from a volume may have both created a snapshot and updated a volume.

3) Actions use the registry to associate them to a resource type. This was largely accomplished in Mitaka, but additional fixes/modifications should be accomplished in Newton. There are three types of actions in a resource type in the registry: item actions, which may operate on only one item; batch actions, which may operate on multiple items, and global actions, which can be operated without any existing items at all. Examples: Edit Image is an item action because only works on a single image; Delete Images is a batch action because it can operate on multiple; and Create Image can be run without any existing image having been created.

4) Details views are exposed via the registry. The registry provides for "details" views, which is a collection of views that are presented to a user when they inquire about a single item. It also provides for summary/drawer views, which are views that complement tabular-style displays. In the case of the details views, these are extensible in so far as a resource type can have zero (preferably one) to many of these, and they could be presented for example as tabs on a "details" page. The drawer views, on the other hand, are registered as having only one, as such a summary is meant to be very limited, and thus is simply replaceable (not having multiple drawer views per item).

Part of this is that there is a standard display for details, where all the component parts of the display are driven by the information in the registry. This alleviates the need for any developer to custom-write their own details pages, and ensures that their views will work seamlessly with any updates to the details framework that may come along. In this case, the details will display any item actions for the selected item, and any detail views that have been registered for the selected item.

There will also be a default view that may be registered for those resource types that have no view specified. This is useful in the case that new resource types are being developed but have no specific views built yet.

5) Angular views share the same Django template as their SPA (single-page app) launching point. This may seem trivial, but right now there are a variety of Django templates each establishing an ng-view. This creates problems because to be a capable SPA we need to be able to use Angular's routing as much as possible rather than constantly re-routing through Django. Having a single Django template that defines the Angular ng-view allows any Django routing to produce the appropriate context for the SPA, yet allows Angular routing to intelligently detect and route within the SPA application.

6) A generic "table" view is available to all registered resource types to minimize coding. What this means is that rather than requiring a developer to write the typical "table" view for a panel, we can instead present a table based on information in the registry for a given resource type. Django routes to the general Django template described above, but the path is parsed to determine the type, which the generic controller then uses to provide the table for that resource type.

To effect this we need to be able to register both a list function and the table columns. The hz-dynamic-table directive is used to provide the table features.

7) A developer panel that inspects the registry is available. The purpose of the developer panel is to show each of the registered resource types and allow a developer to see what members have been registered. This allows not only a good check for configuration, but also the means to easily verify that the actions and views function, without even having any pages present. This is a boon to developers who are tasked with building actions especially when coupled with the ability to dynamically create both table and details views.

Description / Proof of Concept
---------------------------------------

Each of these proofs-of-concept have been demonstrated at https://github.com/palecrow/horizon including Searchlight integration at https://github.com/palecrow/searchlight-ui .

UX
----

The features described here will follow the existing UX guidance provided as for the Angular Image and related work. There are no new complexities introduced by the UI in this functionality.

Testing
----------

All components will be unit-tested at the same coverage and level dictated for the rest of the Angular work.

Outside Dependencies
-------------------------------

None.

Doc Impact
---------------

Documentation for the features needs to be written both within the code but also in the general Horizon developer docs.

Blueprint information

Status:
Complete
Approver:
Rob Cresswell
Priority:
High
Drafter:
Matt Borland
Direction:
Approved
Assignee:
Matt Borland
Definition:
Approved
Series goal:
Accepted for 10.0.0-newton
Implementation:
Implemented
Milestone target:
milestone icon newton-3
Started by
Travis Tripp
Completed by
Rob Cresswell

Related branches

Sprints

Whiteboard

Gerrit topic: https://review.openstack.org/#q,topic:bp/angularize-images-table,n,z

Addressed by: https://review.openstack.org/296590
    Generic details display framework

Addressed by: https://review.openstack.org/309482
    Adding generic table extensibility

Gerrit topic: https://review.openstack.org/#q,topic:useOfActionPromises,n,z

Addressed by: https://review.openstack.org/291846
    Images tables uses action promises

Gerrit topic: https://review.openstack.org/#q,topic:bp/angular-registry,n,z

Addressed by: https://review.openstack.org/316213
    Add OS::Nova::Hypervisor display name registration

Gerrit topic: https://review.openstack.org/#q,topic:resourceBrowser,n,z

Gerrit topic: https://review.openstack.org/#q,topic:resourceBrowser-patch20,n,z

Addressed by: https://review.openstack.org/318125
    Adding generic table features

Addressed by: https://review.openstack.org/313790
    Developer Registry Resource Browser

Addressed by: https://review.openstack.org/309561
    Using registration for auto-generation of Image feature

Addressed by: https://review.openstack.org/324154
    WIP: Documentation improvements for registry

Gerrit topic: https://review.openstack.org/#q,topic:getIdsOfType,n,z

Addressed by: https://review.openstack.org/321207
    getIdsOfType now returns all ids if type undefined

Addressed by: https://review.openstack.org/261376
    Instances: Add angular instances panel

Addressed by: https://review.openstack.org/334065
    Modify hz-cell to use params and to accept values

Addressed by: https://review.openstack.org/334069
    WIP: Adding hz-property and filter/value retrieval from properties

Addressed by: https://review.openstack.org/334083
    WIP: Image uses hz-property for its drawer information

Addressed by: https://review.openstack.org/334103
    Register Neutron Floating IP and Security Group names

Addressed by: https://review.openstack.org/316244
    WIP: Adding actions and views to Instance

Addressed by: https://review.openstack.org/339256
    Adding project name column to ng images

Addressed by: https://review.openstack.org/346174
    hz-resource-table handles transitional states

Addressed by: https://review.openstack.org/346269
    Allow listFunction extra params

Gerrit topic: https://review.openstack.org/#q,topic:ImagesTransitionStatesRegistry,n,z

Gerrit topic: https://review.openstack.org/#q,topic:313790,n,z

Addressed by: https://review.openstack.org/357600
    Pass-through API for client side service calls

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.

Subscribers

No subscribers.