Merge "rest: string → UUID conversion for resource.id to be unique per user"
This commit is contained in:
commit
1ebdf3ec8e
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""no-more-slash
|
"""Remove slashes from original resource IDs, recompute their id with creator
|
||||||
|
|
||||||
Revision ID: 397987e38570
|
Revision ID: 397987e38570
|
||||||
Revises: aba5a217ca9b
|
Revises: aba5a217ca9b
|
||||||
@ -49,7 +49,8 @@ resource_table = sa.Table(
|
|||||||
sqlalchemy_utils.types.uuid.UUIDType(),
|
sqlalchemy_utils.types.uuid.UUIDType(),
|
||||||
nullable=False),
|
nullable=False),
|
||||||
sa.Column('original_resource_id', sa.String(255)),
|
sa.Column('original_resource_id', sa.String(255)),
|
||||||
sa.Column('type', sa.String(255))
|
sa.Column('type', sa.String(255)),
|
||||||
|
sa.Column('creator', sa.String(255))
|
||||||
)
|
)
|
||||||
|
|
||||||
resourcehistory_table = sa.Table(
|
resourcehistory_table = sa.Table(
|
||||||
@ -100,15 +101,28 @@ def upgrade():
|
|||||||
nullable=False),
|
nullable=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
for resource in connection.execute(resource_table.select().where(
|
for resource in connection.execute(resource_table.select()):
|
||||||
resource_table.c.original_resource_id.like('%/%'))):
|
|
||||||
|
if resource_table.c.original_resource_id is None:
|
||||||
|
# statsd resource has no original_resource_id and is NULL
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
orig_as_uuid = uuid.UUID(
|
||||||
|
str(resource_table.c.original_resource_id))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if orig_as_uuid == resource_table.c.id:
|
||||||
|
continue
|
||||||
|
|
||||||
new_original_resource_id = resource.original_resource_id.replace(
|
new_original_resource_id = resource.original_resource_id.replace(
|
||||||
'/', '_')
|
'/', '_')
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
new_original_resource_id = new_original_resource_id.encode('utf-8')
|
new_original_resource_id = new_original_resource_id.encode('utf-8')
|
||||||
new_id = sa.literal(uuidtype.process_bind_param(
|
new_id = sa.literal(uuidtype.process_bind_param(
|
||||||
str(uuid.uuid5(utils.RESOURCE_ID_NAMESPACE,
|
str(utils.ResourceUUID(
|
||||||
new_original_resource_id)),
|
new_original_resource_id, resource.creator)),
|
||||||
connection.dialect))
|
connection.dialect))
|
||||||
|
|
||||||
# resource table
|
# resource table
|
@ -14,6 +14,7 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@ -849,8 +850,10 @@ class ResourceController(rest.RestController):
|
|||||||
|
|
||||||
def __init__(self, resource_type, id):
|
def __init__(self, resource_type, id):
|
||||||
self._resource_type = resource_type
|
self._resource_type = resource_type
|
||||||
|
creator = pecan.request.auth_helper.get_current_user(
|
||||||
|
pecan.request.headers)
|
||||||
try:
|
try:
|
||||||
self.id = utils.ResourceUUID(id)
|
self.id = utils.ResourceUUID(id, creator)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
abort(404, indexer.NoSuchResource(id))
|
abort(404, indexer.NoSuchResource(id))
|
||||||
self.metric = NamedMetricController(str(self.id), self._resource_type)
|
self.metric = NamedMetricController(str(self.id), self._resource_type)
|
||||||
@ -930,8 +933,15 @@ def schema_for(resource_type):
|
|||||||
return ResourceSchema(resource_type.schema)
|
return ResourceSchema(resource_type.schema)
|
||||||
|
|
||||||
|
|
||||||
def ResourceID(value):
|
def ResourceUUID(value, creator):
|
||||||
return (six.text_type(value), utils.ResourceUUID(value))
|
try:
|
||||||
|
return utils.ResourceUUID(value, creator)
|
||||||
|
except ValueError as e:
|
||||||
|
raise voluptuous.Invalid(e)
|
||||||
|
|
||||||
|
|
||||||
|
def ResourceID(value, creator):
|
||||||
|
return (six.text_type(value), ResourceUUID(value, creator))
|
||||||
|
|
||||||
|
|
||||||
class ResourcesController(rest.RestController):
|
class ResourcesController(rest.RestController):
|
||||||
@ -947,7 +957,9 @@ class ResourcesController(rest.RestController):
|
|||||||
# NOTE(sileht): we need to copy the dict because when change it
|
# NOTE(sileht): we need to copy the dict because when change it
|
||||||
# and we don't want that next patch call have the "id"
|
# and we don't want that next patch call have the "id"
|
||||||
schema = dict(schema_for(self._resource_type))
|
schema = dict(schema_for(self._resource_type))
|
||||||
schema["id"] = ResourceID
|
creator = pecan.request.auth_helper.get_current_user(
|
||||||
|
pecan.request.headers)
|
||||||
|
schema["id"] = functools.partial(ResourceID, creator=creator)
|
||||||
|
|
||||||
body = deserialize_and_validate(schema)
|
body = deserialize_and_validate(schema)
|
||||||
body["original_resource_id"], body["id"] = body["id"]
|
body["original_resource_id"], body["id"] = body["id"]
|
||||||
@ -957,8 +969,6 @@ class ResourcesController(rest.RestController):
|
|||||||
}
|
}
|
||||||
target.update(body)
|
target.update(body)
|
||||||
enforce("create resource", target)
|
enforce("create resource", target)
|
||||||
creator = pecan.request.auth_helper.get_current_user(
|
|
||||||
pecan.request.headers)
|
|
||||||
rid = body['id']
|
rid = body['id']
|
||||||
del body['id']
|
del body['id']
|
||||||
try:
|
try:
|
||||||
@ -1004,8 +1014,7 @@ class ResourcesController(rest.RestController):
|
|||||||
def delete(self, **kwargs):
|
def delete(self, **kwargs):
|
||||||
# NOTE(sileht): Don't allow empty filter, this is going to delete
|
# NOTE(sileht): Don't allow empty filter, this is going to delete
|
||||||
# the entire database.
|
# the entire database.
|
||||||
attr_filter = deserialize_and_validate(
|
attr_filter = deserialize_and_validate(ResourceSearchSchema)
|
||||||
SearchResourceTypeController.ResourceSearchSchema)
|
|
||||||
|
|
||||||
# the voluptuous checks everything, but it is better to
|
# the voluptuous checks everything, but it is better to
|
||||||
# have this here.
|
# have this here.
|
||||||
@ -1130,16 +1139,16 @@ class QueryStringSearchAttrFilter(object):
|
|||||||
return cls._parsed_query2dict(parsed_query)
|
return cls._parsed_query2dict(parsed_query)
|
||||||
|
|
||||||
|
|
||||||
def _ResourceSearchSchema(v):
|
def ResourceSearchSchema(v):
|
||||||
"""Helper method to indirect the recursivity of the search schema"""
|
return _ResourceSearchSchema()(v)
|
||||||
return SearchResourceTypeController.ResourceSearchSchema(v)
|
|
||||||
|
|
||||||
|
|
||||||
class SearchResourceTypeController(rest.RestController):
|
def _ResourceSearchSchema():
|
||||||
def __init__(self, resource_type):
|
user = pecan.request.auth_helper.get_current_user(
|
||||||
self._resource_type = resource_type
|
pecan.request.headers)
|
||||||
|
_ResourceUUID = functools.partial(ResourceUUID, creator=user)
|
||||||
|
|
||||||
ResourceSearchSchema = voluptuous.Schema(
|
return voluptuous.Schema(
|
||||||
voluptuous.All(
|
voluptuous.All(
|
||||||
voluptuous.Length(min=0, max=1),
|
voluptuous.Length(min=0, max=1),
|
||||||
{
|
{
|
||||||
@ -1156,31 +1165,36 @@ class SearchResourceTypeController(rest.RestController):
|
|||||||
voluptuous.Length(min=1, max=1),
|
voluptuous.Length(min=1, max=1),
|
||||||
voluptuous.Any(
|
voluptuous.Any(
|
||||||
{"id": voluptuous.Any(
|
{"id": voluptuous.Any(
|
||||||
utils.ResourceUUID, [utils.ResourceUUID]),
|
[_ResourceUUID], _ResourceUUID),
|
||||||
voluptuous.Extra: voluptuous.Extra})),
|
voluptuous.Extra: voluptuous.Extra})),
|
||||||
voluptuous.Any(
|
voluptuous.Any(
|
||||||
u"and", u"∨",
|
u"and", u"∨",
|
||||||
u"or", u"∧",
|
u"or", u"∧",
|
||||||
u"not",
|
u"not",
|
||||||
): voluptuous.All(
|
): voluptuous.All(
|
||||||
[_ResourceSearchSchema], voluptuous.Length(min=1)
|
[ResourceSearchSchema], voluptuous.Length(min=1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse_and_validate_qs_filter(cls, query):
|
class SearchResourceTypeController(rest.RestController):
|
||||||
|
def __init__(self, resource_type):
|
||||||
|
self._resource_type = resource_type
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_and_validate_qs_filter(query):
|
||||||
try:
|
try:
|
||||||
attr_filter = QueryStringSearchAttrFilter.parse(query)
|
attr_filter = QueryStringSearchAttrFilter.parse(query)
|
||||||
except InvalidQueryStringSearchAttrFilter as e:
|
except InvalidQueryStringSearchAttrFilter as e:
|
||||||
raise abort(400, e)
|
raise abort(400, e)
|
||||||
return voluptuous.Schema(cls.ResourceSearchSchema,
|
return voluptuous.Schema(ResourceSearchSchema,
|
||||||
required=True)(attr_filter)
|
required=True)(attr_filter)
|
||||||
|
|
||||||
def _search(self, **kwargs):
|
def _search(self, **kwargs):
|
||||||
if pecan.request.body:
|
if pecan.request.body:
|
||||||
attr_filter = deserialize_and_validate(self.ResourceSearchSchema)
|
attr_filter = deserialize_and_validate(ResourceSearchSchema)
|
||||||
elif kwargs.get("filter"):
|
elif kwargs.get("filter"):
|
||||||
attr_filter = self.parse_and_validate_qs_filter(kwargs["filter"])
|
attr_filter = self.parse_and_validate_qs_filter(kwargs["filter"])
|
||||||
else:
|
else:
|
||||||
@ -1329,13 +1343,16 @@ class SearchMetricController(rest.RestController):
|
|||||||
|
|
||||||
|
|
||||||
class ResourcesMetricsMeasuresBatchController(rest.RestController):
|
class ResourcesMetricsMeasuresBatchController(rest.RestController):
|
||||||
MeasuresBatchSchema = voluptuous.Schema(
|
|
||||||
{ResourceID: {six.text_type: MeasuresListSchema}}
|
|
||||||
)
|
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
def post(self, create_metrics=False):
|
def post(self, create_metrics=False):
|
||||||
body = deserialize_and_validate(self.MeasuresBatchSchema)
|
creator = pecan.request.auth_helper.get_current_user(
|
||||||
|
pecan.request.headers)
|
||||||
|
MeasuresBatchSchema = voluptuous.Schema(
|
||||||
|
{functools.partial(ResourceID, creator=creator):
|
||||||
|
{six.text_type: MeasuresListSchema}}
|
||||||
|
)
|
||||||
|
|
||||||
|
body = deserialize_and_validate(MeasuresBatchSchema)
|
||||||
|
|
||||||
known_metrics = []
|
known_metrics = []
|
||||||
unknown_metrics = []
|
unknown_metrics = []
|
||||||
@ -1350,8 +1367,6 @@ class ResourcesMetricsMeasuresBatchController(rest.RestController):
|
|||||||
|
|
||||||
known_names = [m.name for m in metrics]
|
known_names = [m.name for m in metrics]
|
||||||
if strutils.bool_from_string(create_metrics):
|
if strutils.bool_from_string(create_metrics):
|
||||||
creator = pecan.request.auth_helper.get_current_user(
|
|
||||||
pecan.request.headers)
|
|
||||||
already_exists_names = []
|
already_exists_names = []
|
||||||
for name in names:
|
for name in names:
|
||||||
if name not in known_names:
|
if name not in known_names:
|
||||||
|
@ -134,13 +134,13 @@ tests:
|
|||||||
project_id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
project_id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
||||||
status: 201
|
status: 201
|
||||||
response_headers:
|
response_headers:
|
||||||
location: $SCHEME://$NETLOC/v1/resource/generic/8d835270-2834-5e55-a693-fd0cf91cba3d
|
location: $SCHEME://$NETLOC/v1/resource/generic/2d869568-70d4-5ed6-9891-7d7a3bbf572d
|
||||||
response_json_paths:
|
response_json_paths:
|
||||||
type: generic
|
type: generic
|
||||||
started_at: "2014-01-03T02:02:02+00:00"
|
started_at: "2014-01-03T02:02:02+00:00"
|
||||||
project_id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
project_id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
||||||
created_by_project_id: 99d13f22-3618-4288-82b8-6512ded77e4f
|
created_by_project_id: 99d13f22-3618-4288-82b8-6512ded77e4f
|
||||||
id: 8d835270-2834-5e55-a693-fd0cf91cba3d
|
id: 2d869568-70d4-5ed6-9891-7d7a3bbf572d
|
||||||
original_resource_id: 1.2.3.4
|
original_resource_id: 1.2.3.4
|
||||||
|
|
||||||
- name: get status denied
|
- name: get status denied
|
||||||
|
@ -244,7 +244,7 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.description.cause: "Unknown resources"
|
$.description.cause: "Unknown resources"
|
||||||
$.description.detail:
|
$.description.detail:
|
||||||
- resource_id: "301dbf9a-4fce-52b6-9010-4484c469dcec"
|
- resource_id: "6b8e287d-c01a-538c-979b-a819ee49de5d"
|
||||||
original_resource_id: "foobar"
|
original_resource_id: "foobar"
|
||||||
|
|
||||||
- name: push measurements to named metrics and resource with create_metrics with wrong measure objects
|
- name: push measurements to named metrics and resource with create_metrics with wrong measure objects
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
fixtures:
|
fixtures:
|
||||||
- ConfigFixture
|
- ConfigFixture
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
request_headers:
|
||||||
|
x-user-id: 0fbb231484614b1a80131fc22f6afc9c
|
||||||
|
x-project-id: f3d41b770cc14f0bb94a1d5be9c0e3ea
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
|
|
||||||
- name: list resource type
|
- name: list resource type
|
||||||
@ -222,8 +227,6 @@ tests:
|
|||||||
- name: post invalid resource
|
- name: post invalid resource
|
||||||
POST: /v1/resource/my_custom_resource
|
POST: /v1/resource/my_custom_resource
|
||||||
request_headers:
|
request_headers:
|
||||||
x-user-id: 0fbb2314-8461-4b1a-8013-1fc22f6afc9c
|
|
||||||
x-project-id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
||||||
@ -239,8 +242,6 @@ tests:
|
|||||||
- name: post invalid resource uuid
|
- name: post invalid resource uuid
|
||||||
POST: $LAST_URL
|
POST: $LAST_URL
|
||||||
request_headers:
|
request_headers:
|
||||||
x-user-id: 0fbb2314-8461-4b1a-8013-1fc22f6afc9c
|
|
||||||
x-project-id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
||||||
@ -258,8 +259,6 @@ tests:
|
|||||||
- name: post custom resource
|
- name: post custom resource
|
||||||
POST: $LAST_URL
|
POST: $LAST_URL
|
||||||
request_headers:
|
request_headers:
|
||||||
x-user-id: 0fbb2314-8461-4b1a-8013-1fc22f6afc9c
|
|
||||||
x-project-id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
id: d11edfca-4393-4fda-b94d-b05a3a1b3747
|
||||||
@ -276,8 +275,6 @@ tests:
|
|||||||
- name: patch custom resource
|
- name: patch custom resource
|
||||||
PATCH: /v1/resource/my_custom_resource/d11edfca-4393-4fda-b94d-b05a3a1b3747
|
PATCH: /v1/resource/my_custom_resource/d11edfca-4393-4fda-b94d-b05a3a1b3747
|
||||||
request_headers:
|
request_headers:
|
||||||
x-user-id: 0fbb2314-8461-4b1a-8013-1fc22f6afc9c
|
|
||||||
x-project-id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
name: foo
|
name: foo
|
||||||
@ -303,8 +300,6 @@ tests:
|
|||||||
- name: post resource with default
|
- name: post resource with default
|
||||||
POST: /v1/resource/my_custom_resource
|
POST: /v1/resource/my_custom_resource
|
||||||
request_headers:
|
request_headers:
|
||||||
x-user-id: 0fbb2314-8461-4b1a-8013-1fc22f6afc9c
|
|
||||||
x-project-id: f3d41b77-0cc1-4f0b-b94a-1d5be9c0e3ea
|
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
data:
|
data:
|
||||||
id: c4110aec-6e5c-43fa-b8c5-ffdfbca3ce59
|
id: c4110aec-6e5c-43fa-b8c5-ffdfbca3ce59
|
||||||
|
@ -66,8 +66,26 @@ tests:
|
|||||||
project_id: f3d41b770cc14f0bb94a1d5be9c0e3ea
|
project_id: f3d41b770cc14f0bb94a1d5be9c0e3ea
|
||||||
status: 400
|
status: 400
|
||||||
response_strings:
|
response_strings:
|
||||||
- "Invalid input: not a valid value for dictionary value @ data["
|
- "'/' is not supported in resource id"
|
||||||
- "'id'] "
|
|
||||||
|
|
||||||
|
- name: post new resource non uuid again different user
|
||||||
|
POST: /v1/resource/generic
|
||||||
|
request_headers:
|
||||||
|
x-user-id: 0fbb231484614b1a80131fc22f6afc9b
|
||||||
|
x-project-id: f3d41b770cc14f0bb94a1d5be9c0e3ea
|
||||||
|
data:
|
||||||
|
id: generic zero
|
||||||
|
metrics:
|
||||||
|
cpu.util:
|
||||||
|
archive_policy_name: medium
|
||||||
|
status: 201
|
||||||
|
response_json_paths:
|
||||||
|
created_by_user_id: 0fbb231484614b1a80131fc22f6afc9b
|
||||||
|
created_by_project_id: f3d41b770cc14f0bb94a1d5be9c0e3ea
|
||||||
|
response_headers:
|
||||||
|
# is a UUID
|
||||||
|
location: /v1/resource/generic/[a-f0-9-]{36}/
|
||||||
|
|
||||||
- name: post new resource non uuid
|
- name: post new resource non uuid
|
||||||
POST: /v1/resource/generic
|
POST: /v1/resource/generic
|
||||||
@ -151,7 +169,7 @@ tests:
|
|||||||
archive_policy_name: medium
|
archive_policy_name: medium
|
||||||
status: 400
|
status: 400
|
||||||
response_strings:
|
response_strings:
|
||||||
- not a valid value for
|
- transformable resource id >255 max allowed characters for dictionary value
|
||||||
|
|
||||||
- name: post long non uuid resource id
|
- name: post long non uuid resource id
|
||||||
POST: $LAST_URL
|
POST: $LAST_URL
|
||||||
|
@ -39,23 +39,24 @@ LOG = log.getLogger(__name__)
|
|||||||
RESOURCE_ID_NAMESPACE = uuid.UUID('0a7a15ff-aa13-4ac2-897c-9bdf30ce175b')
|
RESOURCE_ID_NAMESPACE = uuid.UUID('0a7a15ff-aa13-4ac2-897c-9bdf30ce175b')
|
||||||
|
|
||||||
|
|
||||||
def ResourceUUID(value):
|
def ResourceUUID(value, creator):
|
||||||
if isinstance(value, uuid.UUID):
|
if isinstance(value, uuid.UUID):
|
||||||
return value
|
return value
|
||||||
if '/' in value:
|
if '/' in value:
|
||||||
raise ValueError("'/' is not supported in resource id")
|
raise ValueError("'/' is not supported in resource id")
|
||||||
try:
|
try:
|
||||||
try:
|
return uuid.UUID(value)
|
||||||
return uuid.UUID(value)
|
except ValueError:
|
||||||
except ValueError:
|
if len(value) <= 255:
|
||||||
if len(value) <= 255:
|
# value/creator must be str (unicode) in Python 3 and str (bytes)
|
||||||
if six.PY2:
|
# in Python 2. It's not logical, I know.
|
||||||
value = value.encode('utf-8')
|
if six.PY2:
|
||||||
return uuid.uuid5(RESOURCE_ID_NAMESPACE, value)
|
value = value.encode('utf-8')
|
||||||
raise ValueError(
|
creator = creator.encode('utf-8')
|
||||||
'transformable resource id >255 max allowed characters')
|
return uuid.uuid5(RESOURCE_ID_NAMESPACE,
|
||||||
except Exception as e:
|
value + "\x00" + creator)
|
||||||
raise ValueError(e)
|
raise ValueError(
|
||||||
|
'transformable resource id >255 max allowed characters')
|
||||||
|
|
||||||
|
|
||||||
def UUID(value):
|
def UUID(value):
|
||||||
|
12
releasenotes/notes/uuid5-change-8a8c467d2b2d4c85.yaml
Normal file
12
releasenotes/notes/uuid5-change-8a8c467d2b2d4c85.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
issues:
|
||||||
|
- >-
|
||||||
|
The conversion mechanism provided by the API to convert non-UUID resource
|
||||||
|
id to UUID is now also based on the user creating/accessing the resource.
|
||||||
|
This makes sure that the conversion generates a unique UUID for the user
|
||||||
|
and that several users can use the same string as `original_resource_id`.
|
||||||
|
upgrade:
|
||||||
|
- >-
|
||||||
|
Since `original_resource_id` is now unique per creator, that means users
|
||||||
|
cannot refer to resource by using the `original_resource_id` if the
|
||||||
|
resource was not created by them.
|
@ -111,12 +111,16 @@ RESOURCE_IDS=(
|
|||||||
"5a301761-cccc-46e2-8900-8b4f6fe6675a"
|
"5a301761-cccc-46e2-8900-8b4f6fe6675a"
|
||||||
)
|
)
|
||||||
# NOTE(sileht): / are now _
|
# NOTE(sileht): / are now _
|
||||||
[ "$have_resource_type_post" ] && RESOURCE_ID_EXT="5a301761_dddd_46e2_8900_8b4f6fe6675a"
|
# NOTE(jdanjou): and we reencode for admin:admin, but we cannot authenticate as
|
||||||
|
# admin:admin in basic since ":" is forbidden in any username, so let's use the direct
|
||||||
|
# computed ID
|
||||||
|
[ "$have_resource_type_post" ] && RESOURCE_ID_EXT="517920a9-2e50-58b8-88e8-25fd7aae1d8f"
|
||||||
|
|
||||||
dump_data $GNOCCHI_DATA/new
|
dump_data $GNOCCHI_DATA/new
|
||||||
|
|
||||||
# NOTE(sileht): change the output of the old gnocchi to compare with the new without '/'
|
# NOTE(sileht): change the output of the old gnocchi to compare with the new without '/'
|
||||||
$GSED -i -e "s,5a301761/dddd/46e2/8900/8b4f6fe6675a,5a301761_dddd_46e2_8900_8b4f6fe6675a,g" \
|
$GSED -i -e "s,5a301761/dddd/46e2/8900/8b4f6fe6675a,5a301761_dddd_46e2_8900_8b4f6fe6675a,g" \
|
||||||
-e "s,19235bb9-35ca-5f55-b7db-165cfb033c86,fe1bdabf-d94c-5b3a-af1e-06bdff53f228,g" $GNOCCHI_DATA/old/resources.list
|
-e "s,19235bb9-35ca-5f55-b7db-165cfb033c86,517920a9-2e50-58b8-88e8-25fd7aae1d8f,g" $GNOCCHI_DATA/old/resources.list
|
||||||
|
|
||||||
echo "* Checking output difference between Gnocchi $old_version and $new_version"
|
echo "* Checking output difference between Gnocchi $old_version and $new_version"
|
||||||
diff -uNr $GNOCCHI_DATA/old $GNOCCHI_DATA/new
|
diff -uNr $GNOCCHI_DATA/old $GNOCCHI_DATA/new
|
||||||
|
Loading…
Reference in New Issue
Block a user