blob: b2b68a6b271e4e0a053d9cf74ec2f9f27cadd423 [file] [log] [blame]
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +00001# Copyright 2014 IBM Corp.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import re
16
Ghanshyam1f47cf92016-02-25 04:57:18 +090017from tempest.lib import exceptions
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000018
19
20# Define the minimum and maximum version of the API across all of the
21# REST API. The format of the version is:
22# X.Y where:
23#
24# - X will only be changed if a significant backwards incompatible API
25# change is made which affects the API as whole. That is, something
26# that is only very very rarely incremented.
27#
28# - Y when you make any change to the API. Note that this includes
29# semantic changes which may not affect the input or output formats or
30# even originate in the API code layer. We are not distinguishing
31# between backwards compatible and backwards incompatible changes in
32# the versioning system. It must be made clear in the documentation as
33# to what is a backwards compatible change and what is a backwards
34# incompatible one.
35
36class APIVersionRequest(object):
37 """This class represents an API Version Request.
38
39 This class provides convenience methods for manipulation
40 and comparison of version numbers that we need to do to
41 implement microversions.
Ghanshyam1f47cf92016-02-25 04:57:18 +090042
43 :param version_string: String representation of APIVersionRequest.
44 Correct format is 'X.Y', where 'X' and 'Y' are int values.
45 None value should be used to create Null APIVersionRequest,
46 which is equal to 0.0
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000047 """
48
49 # NOTE: This 'latest' version is a magic number, we assume any
50 # projects(Nova, etc.) never achieve this number.
51 latest_ver_major = 99999
52 latest_ver_minor = 99999
53
54 def __init__(self, version_string=None):
Ghanshyam1f47cf92016-02-25 04:57:18 +090055 """Create an API version request object."""
Ghanshyam395c5b52015-12-04 17:27:16 +090056 # NOTE(gmann): 'version_string' as String "None" will be considered as
57 # invalid version string.
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000058 self.ver_major = 0
59 self.ver_minor = 0
60
61 if version_string is not None:
62 match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0)$",
63 version_string)
64 if match:
65 self.ver_major = int(match.group(1))
66 self.ver_minor = int(match.group(2))
67 elif version_string == 'latest':
68 self.ver_major = self.latest_ver_major
69 self.ver_minor = self.latest_ver_minor
70 else:
71 raise exceptions.InvalidAPIVersionString(
72 version=version_string)
73
74 def __str__(self):
75 """Debug/Logging representation of object."""
76 return ("API Version Request: %s" % self.get_string())
77
78 def is_null(self):
Ghanshyam1f47cf92016-02-25 04:57:18 +090079 """Checks whether version is null.
80
81 Return True if version object is null otherwise False.
82
83 :returns: boolean
84 """
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000085 return self.ver_major == 0 and self.ver_minor == 0
86
87 def _format_type_error(self, other):
88 return TypeError("'%(other)s' should be an instance of '%(cls)s'" %
89 {"other": other, "cls": self.__class__})
90
91 def __lt__(self, other):
92 if not isinstance(other, APIVersionRequest):
93 raise self._format_type_error(other)
94
95 return ((self.ver_major, self.ver_minor) <
96 (other.ver_major, other.ver_minor))
97
98 def __eq__(self, other):
99 if not isinstance(other, APIVersionRequest):
100 raise self._format_type_error(other)
101
102 return ((self.ver_major, self.ver_minor) ==
103 (other.ver_major, other.ver_minor))
104
105 def __gt__(self, other):
106 if not isinstance(other, APIVersionRequest):
107 raise self._format_type_error(other)
108
109 return ((self.ver_major, self.ver_minor) >
110 (other.ver_major, other.ver_minor))
111
112 def __le__(self, other):
113 return self < other or self == other
114
115 def __ne__(self, other):
116 return not self.__eq__(other)
117
118 def __ge__(self, other):
119 return self > other or self == other
120
121 def matches(self, min_version, max_version):
122 """Matches the version object.
123
124 Returns whether the version object represents a version
125 greater than or equal to the minimum version and less than
126 or equal to the maximum version.
127
Ghanshyam1f47cf92016-02-25 04:57:18 +0900128 :param min_version: Minimum acceptable version.
129 :param max_version: Maximum acceptable version.
130 :returns: boolean
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +0000131
132 If min_version is null then there is no minimum limit.
133 If max_version is null then there is no maximum limit.
134 If self is null then raise ValueError
135 """
136
137 if self.is_null():
138 raise ValueError
139 if max_version.is_null() and min_version.is_null():
140 return True
141 elif max_version.is_null():
142 return min_version <= self
143 elif min_version.is_null():
144 return self <= max_version
145 else:
146 return min_version <= self <= max_version
147
148 def get_string(self):
149 """Version string representation.
150
151 Converts object to string representation which if used to create
152 an APIVersionRequest object results in the same version request.
153 """
154 if self.is_null():
155 return None
156 if (self.ver_major == self.latest_ver_major and
157 self.ver_minor == self.latest_ver_minor):
158 return 'latest'
159 return "%s.%s" % (self.ver_major, self.ver_minor)