New data type to support Json lists
The previous Json data type has flaws support Json list. This patch adds new data type to support lists. It also removes the LongText data type which is not very useful in Senlin.
This commit is contained in:
parent
732710eee8
commit
7fb05e1f99
|
@ -25,9 +25,9 @@ def upgrade(migrate_engine):
|
|||
primary_key=True, nullable=False),
|
||||
sqlalchemy.Column('name', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('type', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('spec', types.Json),
|
||||
sqlalchemy.Column('spec', types.Dict),
|
||||
sqlalchemy.Column('permission', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('tags', types.Json),
|
||||
sqlalchemy.Column('tags', types.Dict),
|
||||
sqlalchemy.Column('created_time', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('updated_time', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('deleted_time', sqlalchemy.DateTime),
|
||||
|
@ -56,8 +56,8 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('timeout', sqlalchemy.Integer),
|
||||
sqlalchemy.Column('status', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status_reason', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('tags', types.Json),
|
||||
sqlalchemy.Column('data', types.Json),
|
||||
sqlalchemy.Column('tags', types.Dict),
|
||||
sqlalchemy.Column('data', types.Dict),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
@ -80,8 +80,8 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('deleted_time', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('status', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status_reason', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('tags', types.Json),
|
||||
sqlalchemy.Column('data', types.Json),
|
||||
sqlalchemy.Column('tags', types.Dict),
|
||||
sqlalchemy.Column('data', types.Dict),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
@ -115,8 +115,8 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('cooldown', sqlalchemy.Integer),
|
||||
sqlalchemy.Column('level', sqlalchemy.Integer),
|
||||
sqlalchemy.Column('deleted_time', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('spec', types.Json),
|
||||
sqlalchemy.Column('data', types.Json),
|
||||
sqlalchemy.Column('spec', types.Dict),
|
||||
sqlalchemy.Column('data', types.Dict),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
@ -143,9 +143,9 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('id', sqlalchemy.String(36),
|
||||
primary_key=True, nullable=False),
|
||||
sqlalchemy.Column('name', sqlalchemy.String(63)),
|
||||
sqlalchemy.Column('context', types.Json),
|
||||
sqlalchemy.Column('context', types.Dict),
|
||||
sqlalchemy.Column('target', sqlalchemy.String(36)),
|
||||
sqlalchemy.Column('action', types.LongText),
|
||||
sqlalchemy.Column('action', sqlalchemy.Text),
|
||||
sqlalchemy.Column('cause', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('owner', sqlalchemy.String(36)),
|
||||
sqlalchemy.Column('interval', sqlalchemy.Integer),
|
||||
|
@ -155,10 +155,10 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('control', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status_reason', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('inputs', types.Json),
|
||||
sqlalchemy.Column('outputs', types.Json),
|
||||
sqlalchemy.Column('depends_on', types.Json),
|
||||
sqlalchemy.Column('depended_by', types.Json),
|
||||
sqlalchemy.Column('inputs', types.Dict),
|
||||
sqlalchemy.Column('outputs', types.Dict),
|
||||
sqlalchemy.Column('depends_on', types.List),
|
||||
sqlalchemy.Column('depended_by', types.List),
|
||||
sqlalchemy.Column('deleted_time', sqlalchemy.DateTime),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
|
@ -178,7 +178,7 @@ def upgrade(migrate_engine):
|
|||
sqlalchemy.Column('action', sqlalchemy.String(36)),
|
||||
sqlalchemy.Column('status', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status_reason', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('tags', types.Json),
|
||||
sqlalchemy.Column('tags', types.Dict),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import os
|
||||
|
||||
from oslo.db.sqlalchemy import migration as oslo_migration
|
||||
from oslo_db.sqlalchemy import migration as oslo_migration
|
||||
|
||||
|
||||
INIT_VERSION = 0
|
||||
|
|
|
@ -16,7 +16,7 @@ SQLAlchemy models for Senlin data.
|
|||
|
||||
import uuid
|
||||
|
||||
from oslo.db.sqlalchemy import models
|
||||
from oslo_db.sqlalchemy import models
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
import sqlalchemy
|
||||
|
@ -103,8 +103,8 @@ class Cluster(BASE, SenlinBase, SoftDelete):
|
|||
timeout = sqlalchemy.Column(sqlalchemy.Integer)
|
||||
status = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
status_reason = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
tags = sqlalchemy.Column(types.Json)
|
||||
data = sqlalchemy.Column(types.Json)
|
||||
tags = sqlalchemy.Column(types.Dict)
|
||||
data = sqlalchemy.Column(types.Dict)
|
||||
|
||||
|
||||
class Node(BASE, SenlinBase, SoftDelete):
|
||||
|
@ -129,8 +129,8 @@ class Node(BASE, SenlinBase, SoftDelete):
|
|||
|
||||
status = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
status_reason = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
tags = sqlalchemy.Column(types.Json)
|
||||
data = sqlalchemy.Column(types.Json)
|
||||
tags = sqlalchemy.Column(types.Dict)
|
||||
data = sqlalchemy.Column(types.Dict)
|
||||
|
||||
|
||||
class ClusterLock(BASE, SenlinBase):
|
||||
|
@ -175,8 +175,8 @@ class Policy(BASE, SenlinBase, SoftDelete):
|
|||
cooldown = sqlalchemy.Column(sqlalchemy.Integer)
|
||||
level = sqlalchemy.Column(sqlalchemy.Integer)
|
||||
deleted_time = sqlalchemy.Column(sqlalchemy.DateTime)
|
||||
spec = sqlalchemy.Column(types.Json)
|
||||
data = sqlalchemy.Column(types.Json)
|
||||
spec = sqlalchemy.Column(types.Dict)
|
||||
data = sqlalchemy.Column(types.Dict)
|
||||
|
||||
|
||||
class ClusterPolicies(BASE, SenlinBase):
|
||||
|
@ -207,9 +207,9 @@ class Profile(BASE, SenlinBase, SoftDelete):
|
|||
default=lambda: str(uuid.uuid4()))
|
||||
name = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
type = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
spec = sqlalchemy.Column(types.Json)
|
||||
spec = sqlalchemy.Column(types.Dict)
|
||||
permission = sqlalchemy.Column(sqlalchemy.String(32))
|
||||
tags = sqlalchemy.Column(types.Json)
|
||||
tags = sqlalchemy.Column(types.Dict)
|
||||
created_time = sqlalchemy.Column(sqlalchemy.DateTime)
|
||||
updated_time = sqlalchemy.Column(sqlalchemy.DateTime)
|
||||
deleted_time = sqlalchemy.Column(sqlalchemy.DateTime)
|
||||
|
@ -223,9 +223,9 @@ class Action(BASE, SenlinBase, SoftDelete):
|
|||
id = sqlalchemy.Column('id', sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
name = sqlalchemy.Column(sqlalchemy.String(63))
|
||||
context = sqlalchemy.Column(types.Json)
|
||||
context = sqlalchemy.Column(types.Dict)
|
||||
target = sqlalchemy.Column(sqlalchemy.String(36))
|
||||
action = sqlalchemy.Column(types.LongText)
|
||||
action = sqlalchemy.Column(sqlalchemy.Text)
|
||||
cause = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
owner = sqlalchemy.Column(sqlalchemy.String(36))
|
||||
interval = sqlalchemy.Column(sqlalchemy.Integer)
|
||||
|
@ -235,10 +235,10 @@ class Action(BASE, SenlinBase, SoftDelete):
|
|||
status = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
status_reason = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
control = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
inputs = sqlalchemy.Column(types.Json)
|
||||
outputs = sqlalchemy.Column(types.Json)
|
||||
depends_on = sqlalchemy.Column(types.Json)
|
||||
depended_by = sqlalchemy.Column(types.Json)
|
||||
inputs = sqlalchemy.Column(types.Dict)
|
||||
outputs = sqlalchemy.Column(types.Dict)
|
||||
depends_on = sqlalchemy.Column(types.List)
|
||||
depended_by = sqlalchemy.Column(types.List)
|
||||
deleted_time = sqlalchemy.Column(sqlalchemy.DateTime)
|
||||
|
||||
|
||||
|
|
|
@ -1,27 +1,51 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
|
||||
from sqlalchemy.dialects import mysql
|
||||
from sqlalchemy.ext import mutable
|
||||
from sqlalchemy import types
|
||||
|
||||
|
||||
dumps = json.dumps
|
||||
loads = json.loads
|
||||
class MutableList(mutable.Mutable, list):
|
||||
@classmethod
|
||||
def coerce(cls, key, value):
|
||||
if not isinstance(value, cls):
|
||||
if isinstance(value, list):
|
||||
return cls(value)
|
||||
return mutable.Mutable.coerce(key, value)
|
||||
else:
|
||||
return value
|
||||
|
||||
def __delitem__(self, key):
|
||||
list.__delitem__(self, key)
|
||||
self.changed()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
list.__setitem__(self, key, value)
|
||||
self.changed()
|
||||
|
||||
def __getstate__(self):
|
||||
return list(self)
|
||||
|
||||
def __setstate__(self, state):
|
||||
len = list.__len__(self)
|
||||
list.__delslice__(self, 0, len)
|
||||
list.__add__(self, state)
|
||||
self.changed()
|
||||
|
||||
|
||||
class LongText(types.TypeDecorator):
|
||||
class Dict(types.TypeDecorator):
|
||||
impl = types.Text
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
|
@ -30,27 +54,32 @@ class LongText(types.TypeDecorator):
|
|||
else:
|
||||
return self.impl
|
||||
|
||||
|
||||
class Json(LongText):
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return dumps(value)
|
||||
return json.dumps(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is None:
|
||||
return None
|
||||
return loads(value)
|
||||
return json.loads(value)
|
||||
|
||||
|
||||
def associate_with(sqltype):
|
||||
# TODO(leizhang) When we removed sqlalchemy 0.7 dependence
|
||||
# we can import MutableDict directly and remove ./mutable.py
|
||||
try:
|
||||
from sqlalchemy.ext import mutable
|
||||
mutable.MutableDict.associate_with(Json)
|
||||
except ImportError:
|
||||
from senlin.db.sqlalchemy import mutable
|
||||
mutable.MutableDict.associate_with(Json)
|
||||
class List(types.TypeDecorator):
|
||||
impl = types.Text
|
||||
|
||||
associate_with(LongText)
|
||||
associate_with(Json)
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == 'mysql':
|
||||
return dialect.type_descriptor(mysql.LONGTEXT())
|
||||
else:
|
||||
return self.impl
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return json.dumps(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is None:
|
||||
return None
|
||||
return json.loads(value)
|
||||
|
||||
|
||||
mutable.MutableDict.associate_with(Dict)
|
||||
MutableList.associate_with(List)
|
||||
|
|
Loading…
Reference in New Issue