Skip to content

Commit ec1bf47

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add support to rating rules with start and end"
2 parents c26fc95 + f8da9da commit ec1bf47

8 files changed

Lines changed: 168 additions & 10 deletions

File tree

cloudkittyclient/tests/functional/v1/test_hashmap.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
# License for the specific language governing permissions and limitations
1414
# under the License.
1515
#
16+
from datetime import datetime
17+
from datetime import timedelta
18+
1619
from cloudkittyclient.tests.functional import base
1720

1821

@@ -136,13 +139,15 @@ def test_create_get_delete_field(self):
136139
self.assertEqual(len(resp), 0)
137140

138141
def test_create_get_update_delete_mapping_service(self):
142+
future_date = datetime.now() + timedelta(days=1)
143+
date_iso = future_date.isoformat()
139144
resp = self.runner('hashmap service create', params='testservice')[0]
140145
service_id = resp['Service ID']
141146
self._services.append(service_id)
142147

143148
# Create mapping
144149
resp = self.runner('hashmap mapping create',
145-
params='-s {} 12'.format(service_id))[0]
150+
params=f'-s {service_id} 12 --start {date_iso}')[0]
146151
mapping_id = resp['Mapping ID']
147152
self._mappings.append(mapping_id)
148153
self.assertEqual(resp['Service ID'], service_id)
@@ -173,6 +178,8 @@ def test_create_get_update_delete_mapping_service(self):
173178
'hashmap service delete', params=service_id, has_output=False)
174179

175180
def test_create_get_update_delete_mapping_field(self):
181+
future_date = datetime.now() + timedelta(days=1)
182+
date_iso = future_date.isoformat()
176183
resp = self.runner('hashmap service create', params='testservice')[0]
177184
service_id = resp['Service ID']
178185
self._services.append(service_id)
@@ -185,7 +192,8 @@ def test_create_get_update_delete_mapping_field(self):
185192
# Create mapping
186193
resp = self.runner(
187194
'hashmap mapping create',
188-
params='--field-id {} 12 --value testvalue'.format(field_id))[0]
195+
params=f'--field-id {field_id} 12 --value '
196+
f'testvalue --start {date_iso}')[0]
189197
mapping_id = resp['Mapping ID']
190198
self._mappings.append(service_id)
191199
self.assertEqual(resp['Field ID'], field_id)
@@ -203,6 +211,45 @@ def test_create_get_update_delete_mapping_field(self):
203211
params='--cost 10 {}'.format(mapping_id))[0]
204212
self.assertEqual(float(resp['Cost']), float(10))
205213

214+
def test_create_get_update_delete_mapping_field_started(self):
215+
resp = self.runner('hashmap service create',
216+
params='testservice_date_started')[0]
217+
service_id = resp['Service ID']
218+
self._services.append(service_id)
219+
220+
resp = self.runner(
221+
'hashmap field create',
222+
params='{} testfield_date_started'.format(service_id))[0]
223+
field_id = resp['Field ID']
224+
self._fields.append(field_id)
225+
226+
# Create mapping
227+
resp = self.runner(
228+
'hashmap mapping create',
229+
params=f'--field-id {field_id} 12 --value '
230+
f'testvalue')[0]
231+
mapping_id = resp['Mapping ID']
232+
self._mappings.append(service_id)
233+
self.assertEqual(resp['Field ID'], field_id)
234+
self.assertEqual(float(resp['Cost']), float(12))
235+
self.assertEqual(resp['Value'], 'testvalue')
236+
237+
# Get mapping
238+
resp = self.runner(
239+
'hashmap mapping get', params=mapping_id)[0]
240+
self.assertEqual(resp['Mapping ID'], mapping_id)
241+
self.assertEqual(float(resp['Cost']), float(12))
242+
243+
# Should not be able to update a rule that is running (start < now)
244+
try:
245+
self.runner('hashmap mapping update',
246+
params='--cost 10 {}'.format(mapping_id))[0]
247+
except RuntimeError as e:
248+
expected_error = ("You are allowed to update only the attribute "
249+
"[end] as this rule is already running as it "
250+
"started on ")
251+
self.assertIn(expected_error, str(e))
252+
206253
def test_group_mappings_get(self):
207254
# Service and group
208255
resp = self.runner('hashmap service create', params='testservice')[0]

cloudkittyclient/tests/functional/v1/test_pyscripts.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
# License for the specific language governing permissions and limitations
1414
# under the License.
1515
#
16+
from datetime import datetime
17+
from datetime import timedelta
18+
1619
from cloudkittyclient.tests.functional import base
1720

1821

@@ -23,9 +26,12 @@ def __init__(self, *args, **kwargs):
2326
self.runner = self.cloudkitty
2427

2528
def test_create_get_update_list_delete(self):
29+
future_date = datetime.now() + timedelta(days=1)
30+
date_iso = future_date.isoformat()
2631
# Create
2732
resp = self.runner(
28-
'pyscript create', params="testscript 'return 0'")[0]
33+
'pyscript create', params=f"testscript "
34+
f"'return 0' --start {date_iso}")[0]
2935
script_id = resp['Script ID']
3036
self.assertEqual(resp['Name'], 'testscript')
3137

@@ -37,22 +43,59 @@ def test_create_get_update_list_delete(self):
3743
# Update
3844
resp = self.runner(
3945
'pyscript update',
40-
params="-n newname -d 'return 1' {}".format(script_id))[0]
41-
self.assertEqual(resp['Name'], 'newname')
46+
params="-d 'return 1' {} --description "
47+
"desc".format(script_id))[0]
48+
self.assertEqual(resp['Script Description'], 'desc')
4249
self.assertEqual(resp['Script ID'], script_id)
4350
self.assertEqual(resp['Data'], 'return 1')
4451

4552
# List
4653
resp = self.runner('pyscript list')
4754
self.assertEqual(len(resp), 1)
4855
resp = resp[0]
49-
self.assertEqual(resp['Name'], 'newname')
56+
self.assertEqual(resp['Script Description'], 'desc')
5057
self.assertEqual(resp['Script ID'], script_id)
5158
self.assertEqual(resp['Data'], 'return 1')
5259

5360
# Delete
5461
self.runner('pyscript delete', params=script_id, has_output=False)
5562

63+
def test_create_get_update_list_delete_started(self):
64+
# Create
65+
resp = self.runner(
66+
'pyscript create', params="testscript_started "
67+
"'return 0'")[0]
68+
script_id = resp['Script ID']
69+
self.assertEqual(resp['Name'], 'testscript_started')
70+
71+
# Get
72+
resp = self.runner('pyscript get', params=script_id)[0]
73+
self.assertEqual(resp['Name'], 'testscript_started')
74+
self.assertEqual(resp['Script ID'], script_id)
75+
76+
# Should not be able to update a rule that is running (start < now)
77+
try:
78+
self.runner(
79+
'pyscript update',
80+
params="-d 'return 1' {} --description "
81+
"desc".format(script_id))[0]
82+
except RuntimeError as e:
83+
expected_error = ("You are allowed to update only the attribute "
84+
"[end] as this rule is already running as it "
85+
"started on ")
86+
self.assertIn(expected_error, str(e))
87+
88+
# List
89+
resp = self.runner('pyscript list')
90+
self.assertEqual(len(resp), 1)
91+
resp = resp[0]
92+
self.assertEqual(resp['Script Description'], None)
93+
self.assertEqual(resp['Script ID'], script_id)
94+
self.assertEqual(resp['Data'], 'return 0')
95+
96+
# Delete
97+
self.runner('pyscript delete', params=script_id, has_output=False)
98+
5699

57100
class OSCPyscriptTest(CkPyscriptTest):
58101

cloudkittyclient/tests/unit/v1/test_hashmap.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ def test_get_mapping_no_args(self):
110110
self.assertRaises(exc.ArgumentRequired, self.hashmap.get_mapping)
111111

112112
def test_create_mapping(self):
113-
kwargs = dict(cost=2, value='value', field_id='field_id')
113+
kwargs = dict(cost=2, value='value', field_id='field_id',
114+
name='name', start="2024-01-01",
115+
end="2024-01-01",
116+
description="description")
114117
body = dict(
115118
cost=kwargs.get('cost'),
116119
value=kwargs.get('value'),
@@ -119,6 +122,10 @@ def test_create_mapping(self):
119122
group_id=kwargs.get('group_id'),
120123
tenant_id=kwargs.get('tenant_id'),
121124
type=kwargs.get('type') or 'flat',
125+
start="2024-01-01",
126+
end="2024-01-01",
127+
description="description",
128+
name='name'
122129
)
123130
self.hashmap.create_mapping(**kwargs)
124131
self.api_client.post.assert_called_once_with(

cloudkittyclient/tests/unit/v1/test_pyscripts.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def test_get_script_no_arg(self):
3838
self.assertRaises(exc.ArgumentRequired, self.pyscripts.get_script)
3939

4040
def test_create_script(self):
41-
kwargs = dict(name='name', data='data')
41+
kwargs = dict(name='name', data='data', start=None,
42+
end=None, description=None)
4243
self.pyscripts.create_script(**kwargs)
4344
self.api_client.post.assert_called_once_with(
4445
'/v1/rating/module_config/pyscripts/scripts/', json=kwargs)

cloudkittyclient/v1/rating/hashmap.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# License for the specific language governing permissions and limitations
1414
# under the License.
1515
#
16+
import uuid
17+
1618
from cloudkittyclient.common import base
1719
from cloudkittyclient import exc
1820

@@ -171,6 +173,14 @@ def create_mapping(self, **kwargs):
171173
:type type: str
172174
:param value: Value of the mapping
173175
:type value: str
176+
:param name: Name of the mapping
177+
:type name: str
178+
:param start: Date the mapping starts being valid
179+
:type start: str
180+
:param end: Date the mapping stops being valid
181+
:type end: str
182+
:param description: Description of the mapping
183+
:type description: str
174184
"""
175185
if kwargs.get('cost') is None:
176186
raise exc.ArgumentRequired("'cost' argument is required")
@@ -196,6 +206,16 @@ def create_mapping(self, **kwargs):
196206
tenant_id=kwargs.get('tenant_id'),
197207
type=kwargs.get('type') or 'flat',
198208
)
209+
if kwargs.get('description'):
210+
body['description'] = kwargs.get('description')
211+
if kwargs.get('start'):
212+
body['start'] = kwargs.get('start')
213+
if kwargs.get('end'):
214+
body['end'] = kwargs.get('end')
215+
if kwargs.get('name'):
216+
body['name'] = kwargs.get('name')
217+
else:
218+
body['name'] = uuid.uuid4().hex[:24]
199219
url = self.get_url('mappings', kwargs)
200220
return self.api_client.post(url, json=body).json()
201221

cloudkittyclient/v1/rating/hashmap_cli.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ class CliCreateMapping(lister.Lister):
257257
('service_id', 'Service ID'),
258258
('group_id', 'Group ID'),
259259
('tenant_id', 'Project ID'),
260+
('name', 'Mapping Name'),
261+
('start', 'Mapping Start Date'),
262+
('end', 'Mapping End Date'),
263+
('Description', 'Mapping Description')
260264
]
261265

262266
def take_action(self, parsed_args):
@@ -275,6 +279,11 @@ def get_parser(self, prog_name):
275279
parser.add_argument('-t', '--type', type=str, help='Mapping type')
276280
parser.add_argument('--value', type=str, help='Value')
277281
parser.add_argument('cost', type=float, help='Cost')
282+
parser.add_argument('--name', type=str, help='Mapping Name')
283+
parser.add_argument('--start', type=str, help='Mapping Start')
284+
parser.add_argument('--end', type=str, help='Mapping End')
285+
parser.add_argument('--description', type=str,
286+
help='Mapping Description')
278287
return parser
279288

280289

@@ -321,6 +330,11 @@ def get_parser(self, prog_name):
321330
parser.add_argument('--value', type=str, help='Value')
322331
parser.add_argument('--cost', type=str, help='Cost')
323332
parser.add_argument('mapping_id', type=str, help='Mapping ID')
333+
parser.add_argument('--name', type=str, help='Mapping Name')
334+
parser.add_argument('--start', type=str, help='Mapping Start')
335+
parser.add_argument('--end', type=str, help='Mapping End')
336+
parser.add_argument('--description', type=str,
337+
help='Mapping Description')
324338
return parser
325339

326340

cloudkittyclient/v1/rating/pyscripts.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,22 @@ def create_script(self, **kwargs):
5050
:type name: str
5151
:param data: Content of the script
5252
:type data: str
53+
:param start: Date the script starts being valid
54+
:type start: str
55+
:param end: Date the script stops being valid
56+
:type end: str
57+
:param description: Description of the script
58+
:type description: str
5359
"""
5460
for arg in ('name', 'data'):
5561
if not kwargs.get(arg):
5662
raise exc.ArgumentRequired(
5763
"'Argument {} is required.'".format(arg))
5864
url = self.get_url('scripts', kwargs)
59-
body = dict(name=kwargs['name'], data=kwargs['data'])
65+
body = dict(name=kwargs['name'], data=kwargs['data'],
66+
start=kwargs.get('start'),
67+
end=kwargs.get('end'),
68+
description=kwargs.get('description'))
6069
return self.api_client.post(url, json=body).json()
6170

6271
def update_script(self, **kwargs):
@@ -68,11 +77,17 @@ def update_script(self, **kwargs):
6877
:type name: str
6978
:param data: Content of the script
7079
:type data: str
80+
:param start: Date the script starts being valid
81+
:type start: str
82+
:param end: Date the script stops being valid
83+
:type end: str
84+
:param description: Description of the script
85+
:type description: str
7186
"""
7287
if not kwargs.get('script_id'):
7388
raise exc.ArgumentRequired("Argument 'script_id' is required.")
7489
script = self.get_script(script_id=kwargs['script_id'])
75-
for key in ('name', 'data'):
90+
for key in ('name', 'data', 'start', 'end', 'description'):
7691
if kwargs.get(key):
7792
script[key] = kwargs[key]
7893
script.pop('checksum', None)

cloudkittyclient/v1/rating/pyscripts_cli.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class BaseScriptCli(lister.Lister):
2626
('script_id', 'Script ID'),
2727
('checksum', 'Checksum'),
2828
('data', 'Data'),
29+
('start', 'Script Start Date'),
30+
('end', 'Script End Date'),
31+
('description', 'Script Description')
2932
]
3033

3134

@@ -82,6 +85,10 @@ def get_parser(self, prog_name):
8285
parser = super(CliCreateScript, self).get_parser(prog_name)
8386
parser.add_argument('name', type=str, help='Script Name')
8487
parser.add_argument('data', type=str, help='Script Data or data file')
88+
parser.add_argument('--start', type=str, help='Script Start')
89+
parser.add_argument('--end', type=str, help='Script End')
90+
parser.add_argument('--description', type=str,
91+
help='Script Description')
8592
return parser
8693

8794

@@ -107,6 +114,10 @@ def get_parser(self, prog_name):
107114
parser.add_argument('-n', '--name', type=str, help='Script Name')
108115
parser.add_argument('-d', '--data', type=str,
109116
help='Script Data or data file')
117+
parser.add_argument('--start', type=str, help='Script Start')
118+
parser.add_argument('--end', type=str, help='Script End')
119+
parser.add_argument('--description', type=str,
120+
help='Script Description')
110121
return parser
111122

112123

0 commit comments

Comments
 (0)