Merge "Add Project tags"

This commit is contained in:
Jenkins 2017-05-25 02:40:41 +00:00 committed by Gerrit Code Review
commit 9cdd9456ce
1 changed files with 441 additions and 0 deletions

View File

@ -0,0 +1,441 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
============
Project Tags
============
Blueprint `project-tags
<https://blueprints.launchpad.net/keystone/+spec/project-tags>`_
Allow projects in keystone to be taggable with simple strings. This will
make projects more easily categorizable and filterable. This specification
follows closely with neutron's [0]_ resource tag implementation and will
follow the guidelines for using tags set by the OpenStack API Working
Group [1]_.
Problem Description
===================
Today, operators must rely on naming conventions or the extras implementation
in order to tag or categorize projects within keystone. This extras field is
not clearly defined and does not provide a API standard way to retrieve or
filter this data.
Use Case: Project Organization via Tagging
------------------------------------------
In the case of a large private cloud containing many projects with lifespans
that can range from days to a much longer time, there is a need to be able to
tag and categorize projects based on how they are intended to be used, who is
using them, and how long they will exist. The operator would be able to query
all projects with a specific tag without resorting to naming projects with
particular conventions. Additionally, on project modification or deletion,
proper cleanup of these tags could occur without the need of setting up an
external tracking system. Currently, using an external system for keeping
track of tags for projects is difficult for larger scale deployments, where
projects change frequently and are often deleted within a few days.
Proposed Changes
================
* Add a new table ``tags`` to map strings to projects:
.. code:: SQL
CREATE TABLE `tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`project_id` int(11) NOT NULL,
`name` varchar(80) NOT NULL
)
* There is a limit of 50 tags on a project and each tag cannot exceed 60
characters.
* Add tags field as part of default response when listing projects.
* Add new API calls to interact with both project tags for basic CRUD
functionality.
Tags will have the following restrictions as set by the API Working
Group [1]_:
.. Note::
* Tags are case sensitive
* / is not allowed to be in a tag name
* Commas are not allowed to be in a tag name in order to simplify
requests that specify lists of tags
Regex that matches any VALID tag would be:
.. code-block:: bash
\w+|\@|\!|\#|\$|\%|\^|\&|\*|\(|\)|\;|\<|\>|\:|\.|\"|\'|\||\+|\-|\?|\=
The schema for project tags would be:
.. code-block:: json
{
"title": "Project tags",
"type": "array",
"items": {
"$ref": "#/definitions/tag"
},
"definitions": {
"tag": {
"type": "string",
"maxLength": 60,
"maxItems": 50
}
}
}
where if a tag would be added to a project and the max number of items
is exceeded, a 400 Bad Request would be returned.
New API Calls
=============
List all tags for a project
---------------------------
**Request:** ``GET /v3/projects/{project_id}/tags``
**Parameters**
* ``project_id`` - The project ID.
**Response**
* 200 - OK
* 404 - Does not exist
**Response Body**
.. code:: json
{
"tags": ["foo", "bar"]
}
Check if a project contains a specified tag
-------------------------------------------
**Request:** ``GET /v3/projects/{project_id}/tags/{value}``
**Parameters**
* ``project_id`` - The project ID.
* ``value`` - The tag value.
**Response**
* 204 - No Content
* 404 - Tag or Project does not exist
Add single tag to a project
---------------------------
Creates the specified tag and adds it to the list in the project
**Request:** ``PUT /v3/projects/{project_id}/tags/{value}``
**Parameters**
* ``project_id`` - The project ID.
* ``value`` - The tag value.
**Response**
* 201 - Created
* 404 - Project does not exist
**Response Header**
* `Location: http://identity:5000/v3/projects/{project_id}/tags/{value}`
Modify tag list for a project
-----------------------------
Modifies the tags for a project. Any existing tags not
specified will be deleted.
**Request:** ``PUT /v3/projects/{project_id}/tags``
.. code:: json
{
"tags": ["foo", "bar"]
}
**Parameters**
* ``project_id`` - The project ID.
**Response**
* 200 - OK
* 404 - Project does not exist
**Response Body**
.. code:: json
{
"links": {
"next": null,
"previous": null,
"self": "http://identity:5000/v3/projects"
},
"projects": [
{
"description": "Test Project",
"domain_id": "default",
"enabled": true,
"id": "3d4c2c82bd5948f0bcab0cf3a7c9b48c",
"links": {
"self": "http://identity:5000/v3/projects/3d4c2c82bd5948f0bcab0cf3a7c9b48c"
},
"name": "demo",
"tags": ["foo", "bar"]
}
]
}
Delete single tag from project
------------------------------
Remove a single tag from a project.
**Request:** ``DELETE /v3/projects/{project_id}/tags/{value}``
**Parameters**
* ``project_id`` - The project ID.
* ``value`` - The tag to be deleted
**Response**
* 204 - Tags deleted
* 404 - Tag or Project was not found
Remove all tags from a project
------------------------------
Remove the entire tag list from the given project.
**Request:** ``DELETE /v3/projects/{project_id}/tags``
**Parameters**
* ``project_id`` - The project ID.
**Response**
* 204 - Tags deleted
* 404 - Project was not found
Filtering and Searching by Tags
===============================
To search projects by their tags, the client should send a GET request to
the collection URL and include query string parameters that define the
query. These arguments can be combined with other arguments, such as those
that perform additional filtering outside of tags. The recommended query
string arguments for filtering tags are:
.. list-table::
:widths: 100 250
:header-rows: 1
* - Tag Query
- Description
* - tags
- Projects that contain all of the specified tags
* - tags-any
- Projects that contain at least one of the specified tags
* - not-tags
- Projects that do not contain exactly all of the specified tags
* - not-tags-any
- Projects that do not contain any one of the specified tags
To request the list of projects that have a single tag, `tags` argument
should be set to the desired tag name. Example will return all projects
with the "foo" tag:
.. code-block:: bash
GET /v3/projects?tags=foo
To request the list of projects that have two or more tags, the `tags`
argument should be set to the list of tags, separated by commas. In this
situation, the tags given must all be present for a project to be included
in the query result. Example will return all projects that have the "foo"
and "bar" tags:
.. code-block:: bash
GET /v3/projects?tags=foo,bar
To request the list of projects that have one OR more of a list of given
tags, the `tags-any` argument should be set to the list of tags, separated
by commas. In this situation as long as one of the given tags is present,
the project will be included in the query result. Example that returns the
projects that have the “foo” OR “bar” tag:
.. code-block:: bash
GET /v3/projects?tags-any=foo,bar
To request the list of projects that do not have one or more tags, the
`not-tags` argument should be set to the list of tags, separated by commas.
In this situation, only the projects that do not have any of the given tags
will be included in the query results. Example that returns the projects that
do not have the “foo” nor the “bar” tag:
.. code-block:: bash
GET /v3/projects?not-tags=foo,bar
To request the list of projects that do not have at least one of a list of
tags, the `not-tags-any` argument should be set to the list of tags,
separated by commas. In this situation, only the projects that do not have
at least one of the given tags will be included in the query result. Example
that returns the projects that do not have the “foo” tag, or do not have
the “bar” tag:
.. code-block:: bash
GET /v3/projects?not-tags-any=foo,bar
The `tags`, `tags-any`, `not-tags` and `not-tags-any` arguments can
be combined to build more complex queries. Example that returns any projects
that have the “foo” and “bar” tags, plus at least one of “red” and “blue”.
.. code-block:: bash
GET /v3/projects?tags=foo,bar&tags-any=red,blue
Alternatives
============
1. Store the tags external to keystone.
* Pro: No change to keystone required.
* Con: Requires an external tool or work-around. If using an external
system, this requires yet another tool to maintain and keep track of.
Any updates for resources, such as deletion of a project, will require
the corresponding tag data to be kept up-to-date in the external system.
For larger scale deployments with many temporary projects that are
regularly purged, this is both clumsy and difficult to maintain.
2. Store the tags in ``extra`` column.
* Pro: No additional SQL table modification is needed.
* Con: The ``extra`` column currently stores some ancillary data,
e.g. user's email address. Allowing the API to modify this data
may cause conflicts. There is not a standard API way to manipulate
this data and the data is not indexed.
3. Use a naming schema for projects to categorize them.
* Pro: No change in keystone is required.
* Con: If a project is going to need multiple "tags" in its name, this
can cause project names to become very large as well as
ugly/unrecognizable. For a large cloud with many projects, this is
unrealistic.
Security Impact
===============
Typically, only the project admin should be able to create/edit the tags
for a project. This is to prevent unprivileged users from viewing or changing
any existing tags, which could possibly denote administrative functions.
The policy rules for tags will follow the rules set for /v3/projects.
Notifications Impact
====================
Any added API calls should emit the proper notifications.
Other End User Impact
=====================
New API's will be available to operators with appropriate role(s) to
manipulate keystone resource tags.
Performance Impact
==================
There will be no performance impact on existing APIs. There may be database
performance impact if operators allow for a large number of tags to be
associated with projects.
Other Deployer Impact
=====================
None.
Developer Impact
================
None.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
* Gage Hugo - gagehugo@gmail.com (IRC gagehugo)
Other contributors:
* Samuel Pilla - sp516w@att.com (IRC spilla)
* Tin Lam - tinlam@gmail.com (IRC lamt)
Work Items
----------
1. Implement the new API calls
2. Add relevent tests
3. Update all appropriate documentation/api-ref
4. Update keystone-client/openstack-cli
Dependencies
============
None.
Documentation Impact
====================
Update ``api-ref`` documents to show the usage of the API's.
References
==========
.. [0] `<http://docs.openstack.org/newton/networking-guide/ops-resource-tags.html>`_
.. [1] `<https://specs.openstack.org/openstack/api-wg/guidelines/tags.html>`_