From 985e66a8debdfc3bb6ce9f3157c166c739ec9e62 Mon Sep 17 00:00:00 2001 From: Richard Theis Date: Fri, 25 Mar 2016 15:40:28 -0500 Subject: [PATCH] Consistent resource.prop for timestamps and booleans (cluster) This patch set updates all cluster objects to use consistent resource.prop for timestamps and booleans. In particular, the following changes were made: - Clarify documentation for timestamp and boolean attributes - Use 'is_' prefix and boolean type for boolean attributes - Use '_at' suffix and timestamp type for timestamp attributes Change-Id: Ie08fcddf47643fabb2bacdc74bc1c582b1598fb9 Partial-Bug: #1544584 --- openstack/cluster/v1/action.py | 13 ++++++--- openstack/cluster/v1/cluster.py | 10 ++++--- openstack/cluster/v1/cluster_policy.py | 4 +-- openstack/cluster/v1/event.py | 3 ++- openstack/cluster/v1/node.py | 10 ++++--- openstack/cluster/v1/policy.py | 7 +++-- openstack/cluster/v1/profile.py | 7 +++-- openstack/cluster/v1/receiver.py | 7 +++-- .../tests/unit/cluster/v1/test_action.py | 27 +++++++++++++------ .../tests/unit/cluster/v1/test_cluster.py | 21 ++++++++++++--- .../unit/cluster/v1/test_cluster_policy.py | 2 +- openstack/tests/unit/cluster/v1/test_event.py | 8 ++++-- openstack/tests/unit/cluster/v1/test_node.py | 20 +++++++++++--- .../tests/unit/cluster/v1/test_policy.py | 14 +++++++--- .../tests/unit/cluster/v1/test_profile.py | 12 ++++++++- .../tests/unit/cluster/v1/test_receiver.py | 14 +++++++--- 16 files changed, 134 insertions(+), 45 deletions(-) diff --git a/openstack/cluster/v1/action.py b/openstack/cluster/v1/action.py index 06c85e023..1cea89ca1 100644 --- a/openstack/cluster/v1/action.py +++ b/openstack/cluster/v1/action.py @@ -12,6 +12,7 @@ from openstack.cluster import cluster_service +from openstack import format from openstack import resource @@ -39,9 +40,11 @@ class Action(resource.Resource): #: Interval in seconds between two consecutive executions. interval = resource.prop('interval') #: The time the action was started. - start_time = resource.prop('start_time') + #: *Type: datetime object parsed from a UNIX epoch* + start_at = resource.prop('start_time', type=format.UNIXEpoch) #: The time the action completed execution. - end_time = resource.prop('end_time') + #: *Type: datetime object parsed from a UNIX epoch* + end_at = resource.prop('end_time', type=format.UNIXEpoch) #: The timeout in seconds. timeout = resource.prop('timeout') #: Current status of the action. @@ -58,6 +61,8 @@ class Action(resource.Resource): #: A list of actions that can start only after this action has finished. depended_by = resource.prop('depended_by', type=list) #: Timestamp when the action is created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: Timestamp when the action was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) diff --git a/openstack/cluster/v1/cluster.py b/openstack/cluster/v1/cluster.py index 5fca92e19..52e91ba53 100644 --- a/openstack/cluster/v1/cluster.py +++ b/openstack/cluster/v1/cluster.py @@ -11,6 +11,7 @@ # under the License. from openstack.cluster import cluster_service +from openstack import format from openstack import resource from openstack import utils @@ -43,11 +44,14 @@ class Cluster(resource.Resource): #: The ID of the parent cluster (if any). parent_id = resource.prop('parent') #: Timestamp of when the cluster was initialized. - init_at = resource.prop('init_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + init_at = resource.prop('init_at', type=format.ISO8601) #: Timestamp of when the cluster was created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: Timestamp of when the cluster was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) #: Lower bound (inclusive) for the size of the cluster. min_size = resource.prop('min_size', type=int) #: Upper bound (inclusive) for the size of the cluster. A value of diff --git a/openstack/cluster/v1/cluster_policy.py b/openstack/cluster/v1/cluster_policy.py index d4abbc6be..f978d99ef 100644 --- a/openstack/cluster/v1/cluster_policy.py +++ b/openstack/cluster/v1/cluster_policy.py @@ -36,7 +36,7 @@ class ClusterPolicy(resource.Resource): cluster_name = resource.prop('cluster_name') #: Type string of the policy. policy_type = resource.prop('policy_type') - #: Whether the policy is enabled on the cluster. - enabled = resource.prop('enabled') + #: Whether the policy is enabled on the cluster. *Type: bool* + is_enabled = resource.prop('enabled', type=bool) #: Data associated with the cluster-policy binding. data = resource.prop('data', type=dict) diff --git a/openstack/cluster/v1/event.py b/openstack/cluster/v1/event.py index d16bc9db5..011041fab 100644 --- a/openstack/cluster/v1/event.py +++ b/openstack/cluster/v1/event.py @@ -12,6 +12,7 @@ from openstack.cluster import cluster_service +from openstack import format from openstack import resource @@ -27,7 +28,7 @@ class Event(resource.Resource): # Properties id = resource.prop('id') - timestamp = resource.prop('timestamp') + timestamp = resource.prop('timestamp', type=format.ISO8601) obj_id = resource.prop('obj_id') obj_name = resource.prop('obj_name') obj_type = resource.prop('obj_type') diff --git a/openstack/cluster/v1/node.py b/openstack/cluster/v1/node.py index de7287ac1..9c6ca8183 100644 --- a/openstack/cluster/v1/node.py +++ b/openstack/cluster/v1/node.py @@ -11,6 +11,7 @@ # under the License. from openstack.cluster import cluster_service +from openstack import format from openstack import resource from openstack import utils @@ -50,12 +51,15 @@ class Node(resource.Resource): #: A string indicating the role the node plays in a cluster. role = resource.prop('role') #: The timestamp of the node object's initialization. - init_at = resource.prop('init_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + init_at = resource.prop('init_at', type=format.ISO8601) #: The timestamp of the node's creation, i.e. the physical object #: represented by this node is also created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: The timestamp the node was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) #: A string indicating the node's status. status = resource.prop('status') #: A string describing why the node entered its current status. diff --git a/openstack/cluster/v1/policy.py b/openstack/cluster/v1/policy.py index 1d1e5a797..f301d37e3 100644 --- a/openstack/cluster/v1/policy.py +++ b/openstack/cluster/v1/policy.py @@ -11,6 +11,7 @@ # under the License. from openstack.cluster import cluster_service +from openstack import format from openstack import resource @@ -35,9 +36,11 @@ class Policy(resource.Resource): #: The type name of the policy. type = resource.prop('type') #: The timestamp when the policy is created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: The timestamp when the policy was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) #: The specification of the policy. spec = resource.prop('spec', type=dict) #: A dictionary containing runtime data of the policy. diff --git a/openstack/cluster/v1/profile.py b/openstack/cluster/v1/profile.py index 7cdb4488b..e7604290e 100644 --- a/openstack/cluster/v1/profile.py +++ b/openstack/cluster/v1/profile.py @@ -11,6 +11,7 @@ # under the License. from openstack.cluster import cluster_service +from openstack import format from openstack import resource @@ -39,6 +40,8 @@ class Profile(resource.Resource): #: A collection of key-value pairs that are attached to the profile. metadata = resource.prop('metadata', type=dict) #: Timestamp of when the profile was created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: Timestamp of when the profile was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) diff --git a/openstack/cluster/v1/receiver.py b/openstack/cluster/v1/receiver.py index e7326e7d7..a55716c52 100644 --- a/openstack/cluster/v1/receiver.py +++ b/openstack/cluster/v1/receiver.py @@ -12,6 +12,7 @@ from openstack.cluster import cluster_service +from openstack import format from openstack import resource @@ -43,9 +44,11 @@ class Receiver(resource.Resource): #: The name of the targeted action. action = resource.prop('action') #: Timestamp of when the receiver was created. - created_at = resource.prop('created_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + created_at = resource.prop('created_at', type=format.ISO8601) #: Timestamp of when the receiver was last updated. - updated_at = resource.prop('updated_at') + #: *Type: datetime object parsed from ISO 8601 formatted string* + updated_at = resource.prop('updated_at', type=format.ISO8601) #: The credential of the impersonated user. actor = resource.prop('actor', type=dict) #: A dictionary containing key-value pairs that are provided to the diff --git a/openstack/tests/unit/cluster/v1/test_action.py b/openstack/tests/unit/cluster/v1/test_action.py index 32acabe61..e96fb4643 100644 --- a/openstack/tests/unit/cluster/v1/test_action.py +++ b/openstack/tests/unit/cluster/v1/test_action.py @@ -10,6 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime +import iso8601 + import testtools from openstack.cluster.v1 import action @@ -25,8 +28,8 @@ FAKE = { 'cause': 'RPC Request', 'owner': None, 'interval': -1, - 'start_time': 144450000.0, - 'end_time': 144450000.0, + 'start_time': 1453414055.48672, + 'end_time': 1453414055.48672, 'timeout': 3600, 'status': 'SUCCEEDED', 'status_reason': 'Action completed successfully.', @@ -34,8 +37,8 @@ FAKE = { 'outputs': {}, 'depends_on': [], 'depended_by': [], - 'created_at': '2015-10-10T04:46:36.000000', - 'updated_at': None, + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', } @@ -62,8 +65,12 @@ class TestAction(testtools.TestCase): self.assertEqual(FAKE['cause'], sot.cause) self.assertEqual(FAKE['owner'], sot.owner_id) self.assertEqual(FAKE['interval'], sot.interval) - self.assertEqual(FAKE['start_time'], sot.start_time) - self.assertEqual(FAKE['end_time'], sot.end_time) + self.assertEqual(datetime.datetime(2016, 1, 21, 22, 7, 35, 486720, + tzinfo=iso8601.UTC), + sot.start_at) + self.assertEqual(datetime.datetime(2016, 1, 21, 22, 7, 35, 486720, + tzinfo=iso8601.UTC), + sot.end_at) self.assertEqual(FAKE['timeout'], sot.timeout) self.assertEqual(FAKE['status'], sot.status) self.assertEqual(FAKE['status_reason'], sot.status_reason) @@ -71,5 +78,9 @@ class TestAction(testtools.TestCase): self.assertEqual(FAKE['outputs'], sot.outputs) self.assertEqual(FAKE['depends_on'], sot.depends_on) self.assertEqual(FAKE['depended_by'], sot.depended_by) - self.assertEqual(FAKE['created_at'], sot.created_at) - self.assertEqual(FAKE['updated_at'], sot.updated_at) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) diff --git a/openstack/tests/unit/cluster/v1/test_cluster.py b/openstack/tests/unit/cluster/v1/test_cluster.py index dcab3b06c..6fc20e100 100644 --- a/openstack/tests/unit/cluster/v1/test_cluster.py +++ b/openstack/tests/unit/cluster/v1/test_cluster.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import mock import testtools @@ -28,14 +30,17 @@ FAKE = { 'profile_id': 'myserver', 'metadata': {}, 'timeout': None, + 'init_at': '2015-10-10T12:46:36.000000', + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', } FAKE_CREATE_RESP = { 'cluster': { 'action': 'a679c926-908f-49e7-a822-06ca371e64e1', - 'init_at': None, - 'created_at': None, - 'updated_at': None, + 'init_at': '2015-10-10T12:46:36.000000', + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', 'data': {}, 'desired_capacity': 1, 'domain': None, @@ -90,6 +95,16 @@ class TestCluster(testtools.TestCase): self.assertEqual(FAKE['timeout'], sot.timeout) self.assertEqual(FAKE['metadata'], sot.metadata) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.init_at.replace(tzinfo=None)) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) + def test_scale_in(self): sot = cluster.Cluster(FAKE) sot['id'] = 'IDENTIFIER' diff --git a/openstack/tests/unit/cluster/v1/test_cluster_policy.py b/openstack/tests/unit/cluster/v1/test_cluster_policy.py index 290c16acd..9f57f2fa9 100644 --- a/openstack/tests/unit/cluster/v1/test_cluster_policy.py +++ b/openstack/tests/unit/cluster/v1/test_cluster_policy.py @@ -48,7 +48,7 @@ class TestClusterPolicy(testtools.TestCase): self.assertEqual(FAKE['cluster_id'], sot.cluster_id) self.assertEqual(FAKE['cluster_name'], sot.cluster_name) self.assertEqual(FAKE['data'], sot.data) - self.assertEqual(FAKE['enabled'], sot.enabled) + self.assertTrue(sot.is_enabled) self.assertEqual(FAKE['policy_id'], sot.policy_id) self.assertEqual(FAKE['policy_name'], sot.policy_name) self.assertEqual(FAKE['policy_type'], sot.policy_type) diff --git a/openstack/tests/unit/cluster/v1/test_event.py b/openstack/tests/unit/cluster/v1/test_event.py index c7b692cb9..82802dde2 100644 --- a/openstack/tests/unit/cluster/v1/test_event.py +++ b/openstack/tests/unit/cluster/v1/test_event.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import testtools from openstack.cluster.v1 import event @@ -28,7 +30,7 @@ FAKE = { 'project': '42d9e9663331431f97b75e25136307ff', 'status': 'START', 'status_reason': 'The action was abandoned.', - 'timestamp': '2015-10-03T03:35:09', + 'timestamp': '2016-10-10T12:46:36.000000', 'user': '5e5bf8027826429c96af157f68dc9072' } @@ -61,5 +63,7 @@ class TestEvent(testtools.TestCase): self.assertEqual(FAKE['project'], sot.project_id) self.assertEqual(FAKE['status'], sot.status) self.assertEqual(FAKE['status_reason'], sot.status_reason) - self.assertEqual(FAKE['timestamp'], sot.timestamp) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.timestamp.replace(tzinfo=None)) self.assertEqual(FAKE['user'], sot.user_id) diff --git a/openstack/tests/unit/cluster/v1/test_node.py b/openstack/tests/unit/cluster/v1/test_node.py index 88b4695e1..308986c06 100644 --- a/openstack/tests/unit/cluster/v1/test_node.py +++ b/openstack/tests/unit/cluster/v1/test_node.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import mock import testtools @@ -27,6 +29,9 @@ FAKE = { 'profile_id': 'myserver', 'index': 1, 'role': 'master', + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', + 'init_at': '2015-10-10T12:46:36.000000', } FAKE_CREATE_RESP = { @@ -35,12 +40,12 @@ FAKE_CREATE_RESP = { 'name': FAKE_NAME, 'cluster_id': '99001122-aabb-ccdd-ffff-efdcab124567', 'action': '1122aabb-eeff-7755-2222-00991234dcba', - 'created_at': None, - 'updated_at': None, + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', 'data': {}, 'role': 'master', 'index': 1, - 'init_time': None, + 'init_at': '2015-10-10T12:46:36.000000', 'metadata': {}, 'profile_id': '560a8f9d-7596-4a32-85e8-03645fa7be13', 'profile_name': 'myserver', @@ -78,6 +83,15 @@ class TestNode(testtools.TestCase): self.assertEqual(FAKE['index'], sot.index) self.assertEqual(FAKE['role'], sot.role) self.assertEqual(FAKE['metadata'], sot.metadata) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.init_at.replace(tzinfo=None)) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) def test_check(self): sot = node.Node(FAKE) diff --git a/openstack/tests/unit/cluster/v1/test_policy.py b/openstack/tests/unit/cluster/v1/test_policy.py index 1a5c765be..966e7e3a3 100644 --- a/openstack/tests/unit/cluster/v1/test_policy.py +++ b/openstack/tests/unit/cluster/v1/test_policy.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import testtools from openstack.cluster.v1 import policy @@ -31,8 +33,8 @@ FAKE = { } }, 'type': 'senlin.policy.deletion-1.0', - 'created_at': '2015-08-10T09:14:53', - 'updated_at': None, + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', 'data': {}, } @@ -60,5 +62,9 @@ class TestPolicy(testtools.TestCase): self.assertEqual(FAKE['name'], sot.name) self.assertEqual(FAKE['spec'], sot.spec) self.assertEqual(FAKE['data'], sot.data) - self.assertEqual(FAKE['created_at'], sot.created_at) - self.assertEqual(FAKE['updated_at'], sot.updated_at) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) diff --git a/openstack/tests/unit/cluster/v1/test_profile.py b/openstack/tests/unit/cluster/v1/test_profile.py index 39795e4ca..3570f7839 100644 --- a/openstack/tests/unit/cluster/v1/test_profile.py +++ b/openstack/tests/unit/cluster/v1/test_profile.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import testtools from openstack.cluster.v1 import profile @@ -32,7 +34,9 @@ FAKE = { 'name': 'cirros_server' } }, - 'type': 'os.nova.server' + 'type': 'os.nova.server', + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', } @@ -61,3 +65,9 @@ class TestProfile(testtools.TestCase): self.assertEqual(FAKE['metadata'], sot.metadata) self.assertEqual(FAKE['spec'], sot.spec) self.assertEqual(FAKE['type'], sot.type_name) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) diff --git a/openstack/tests/unit/cluster/v1/test_receiver.py b/openstack/tests/unit/cluster/v1/test_receiver.py index f5bdee691..1da31ac4f 100644 --- a/openstack/tests/unit/cluster/v1/test_receiver.py +++ b/openstack/tests/unit/cluster/v1/test_receiver.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + import testtools from openstack.cluster.v1 import receiver @@ -23,8 +25,8 @@ FAKE = { 'type': 'webhook', 'cluster_id': 'FAKE_CLUSTER', 'action': 'CLUSTER_RESIZE', - 'created_at': '2015-08-10T09:14:53', - 'updated_at': None, + 'created_at': '2015-10-10T12:46:36.000000', + 'updated_at': '2016-10-10T12:46:36.000000', 'actor': {}, 'params': { 'adjustment_type': 'CHANGE_IN_CAPACITY', @@ -64,8 +66,12 @@ class TestReceiver(testtools.TestCase): self.assertEqual(FAKE['cluster_id'], sot.cluster_id) self.assertEqual(FAKE['action'], sot.action) self.assertEqual(FAKE['params'], sot.params) - self.assertEqual(FAKE['created_at'], sot.created_at) - self.assertEqual(FAKE['updated_at'], sot.updated_at) + dt = datetime.datetime(2015, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.created_at.replace(tzinfo=None)) + dt = datetime.datetime(2016, 10, 10, 12, 46, 36, 000000).replace( + tzinfo=None) + self.assertEqual(dt, sot.updated_at.replace(tzinfo=None)) self.assertEqual(FAKE['user'], sot.user_id) self.assertEqual(FAKE['project'], sot.project_id) self.assertEqual(FAKE['domain'], sot.domain_id)