Merge lp:~psivaa/uci-engine/data-store-refactor-backport into lp:uci-engine/mthood

Proposed by Para Siva
Status: Merged
Approved by: Para Siva
Approved revision: 416
Merged at revision: 416
Proposed branch: lp:~psivaa/uci-engine/data-store-refactor-backport
Merge into: lp:uci-engine/mthood
Diff against target: 287 lines (+71/-97)
3 files modified
ci-utils/ci_utils/data_store.py (+51/-80)
ci-utils/ci_utils/tests/test_data_store.py (+15/-12)
test_runner/tstrun/tests/test_data_store.py (+5/-5)
To merge this branch: bzr merge lp:~psivaa/uci-engine/data-store-refactor-backport
Reviewer Review Type Date Requested Status
Vincent Ladeuil (community) Approve
Review via email: mp+221200@code.launchpad.net

Commit message

Back porting vila's commit (451) for better swift connection.

Description of the change

Back porting vila's commit (451) for better swift connection.

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

Given you ran tarmac.sh locally and successfully, this should be good to land.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed directory 'ci-utils/ci_utils/data_store'
=== renamed file 'ci-utils/ci_utils/data_store/__init__.py' => 'ci-utils/ci_utils/data_store.py'
--- ci-utils/ci_utils/data_store/__init__.py 2014-03-16 23:17:08 +0000
+++ ci-utils/ci_utils/data_store.py 2014-05-28 10:09:04 +0000
@@ -32,15 +32,12 @@
3232
3333
34class DataStore(object):34class DataStore(object):
35 def __init__(self, component, auth_config, identifier=None, public=False):35
36 self.container = self._get_container(component, identifier)36 def __init__(self, component, auth_config, public=False):
37 self.container_id = component
37 self.auth_config = auth_config38 self.auth_config = auth_config
3839 self.public = public
39 self._setup_auth()40 self.client = None
40
41 self._create_container(self.container)
42 self.change_visibility(public=public)
43 self.container_url = self._get_container_url()
4441
45 @staticmethod42 @staticmethod
46 def validate_auth_config(auth_config):43 def validate_auth_config(auth_config):
@@ -58,15 +55,38 @@
58 "missing fields: {}".format(', '.join(missing_fields))55 "missing fields: {}".format(', '.join(missing_fields))
59 )56 )
6057
58 def ensure_swift_client(self):
59 if self.client is not None:
60 return self.client
61
62 self.validate_auth_config(self.auth_config)
63 config = self.auth_config
64 self.client = client.Connection(
65 authurl=config.get('auth_url'),
66 user=config.get('auth_user'),
67 key=config.get('auth_password'),
68 os_options={'tenant_name': config.get('auth_tenant_name'),
69 'region_name': config.get('auth_region')},
70 auth_version='2.0')
71 try:
72 self._create_container(self.container_id)
73 except client.ClientException:
74 raise DataStoreException("Missing or invalid authentication info.")
75 self.change_visibility(public=self.public)
76 self.container_url = "{}/{}".format(self.client.url, self.container_id)
77
61 def list_files(self):78 def list_files(self):
62 hdr, data = client.get_container(*self.auth_bits)79 self.ensure_swift_client()
63 return [x['name'] for x in data]80 _, objects = self.client.get_container(self.container_id)
81 return [x['name'] for x in objects]
6482
65 def put_file(self, filename, contents, content_type=None):83 def put_file(self, filename, contents, content_type=None):
84 self.ensure_swift_client()
66 name = _get_file_name(filename)85 name = _get_file_name(filename)
67 try:86 try:
68 client.put_object(*self.auth_bits, name=name, contents=contents,87 self.client.put_object(self.container_id, obj=name,
69 content_type=content_type)88 contents=contents,
89 content_type=content_type)
70 except ClientException as e:90 except ClientException as e:
71 raise DataStoreException(91 raise DataStoreException(
72 "Failed to upload file: {}, Error: {}".format(filename, e)92 "Failed to upload file: {}, Error: {}".format(filename, e)
@@ -74,48 +94,48 @@
7494
75 return self.file_path(filename)95 return self.file_path(filename)
7696
77 def get_file(self, filename, with_headers=False):97 def get_file(self, filename):
98 self.ensure_swift_client()
78 name = _get_file_name(filename)99 name = _get_file_name(filename)
79100
80 contents = None101 contents = None
81 try:102 try:
82 hdr, contents = client.get_object(*self.auth_bits, name=name)103 hdr, contents = self.client.get_object(self.container_id, obj=name)
83 except ClientException as e:104 except ClientException as e:
84 raise DataStoreException(105 raise DataStoreException(
85 "Failed to get file: {}, Error: {}".format(filename, e)106 "Failed to get file: {}, Error: {}".format(filename, e)
86 )107 )
87
88 if with_headers:
89 return hdr, contents
90
91 return contents108 return contents
92109
93 def change_visibility(self, public=False):110 def change_visibility(self, public=False):
94 read_acl = ''111 self.ensure_swift_client()
95
96 if public:112 if public:
97 read_acl = '.r:*'113 read_acl = '.r:*'
98114 else:
99 args = self.auth_bits115 read_acl = ''
100 args += ({'X-Container-Read': read_acl},)116 self.client.post_container(self.container_id,
101 client.post_container(*args)117 {'X-Container-Read': read_acl})
118 self.public = public
102119
103 def delete_file(self, filename):120 def delete_file(self, filename):
121 self.ensure_swift_client()
104 name = _get_file_name(filename)122 name = _get_file_name(filename)
105 try:123 try:
106 client.delete_object(*self.auth_bits, name=name)124 self.client.delete_object(self.container_id, obj=name)
107 except ClientException as e:125 except ClientException as e:
108 raise DataStoreException(126 raise DataStoreException(
109 "Failed to delete file: {}, Error: {}".format(filename, e)127 "Failed to delete file: {}, Error: {}".format(filename, e)
110 )128 )
111129
112 def clear(self):130 def clear(self):
131 self.ensure_swift_client()
113 try:132 try:
114 files = client.get_container(*self.auth_bits)[1]133 files = self.client.get_container(self.container_id)[1]
115134
116 for file in files:135 for f in files:
117 try:136 try:
118 client.delete_object(*self.auth_bits, name=file['name'])137 self.client.delete_object(self.container_id,
138 obj=f['name'])
119 except ClientException as e:139 except ClientException as e:
120 raise DataStoreException(140 raise DataStoreException(
121 "Failed to delete file: {}".format(e)141 "Failed to delete file: {}".format(e)
@@ -126,11 +146,12 @@
126 )146 )
127147
128 def delete(self, recursive=False):148 def delete(self, recursive=False):
149 self.ensure_swift_client()
129 try:150 try:
130 if recursive:151 if recursive:
131 self.clear()152 self.clear()
132153
133 client.delete_container(*self.auth_bits)154 self.client.delete_container(self.container_id)
134 except ClientException as e:155 except ClientException as e:
135 raise DataStoreException(156 raise DataStoreException(
136 "Failed to delete container: {}".format(e)157 "Failed to delete container: {}".format(e)
@@ -141,55 +162,5 @@
141162
142 return "{}/{}".format(self.container_url, name)163 return "{}/{}".format(self.container_url, name)
143164
144 # Private functions
145 def _has_file(self, filename):
146 name = _get_file_name(filename)
147 result = True
148
149 try:
150 client.head_object(*self.auth_bits, name=name)
151 except ClientException:
152 result = False
153
154 return result
155
156 def _get_container(self, component, identifier=None):
157 container = component
158
159 if identifier is not None and identifier != "":
160 container = "{}.{}".format(container, identifier)
161
162 return container
163
164 def _setup_auth(self):
165 config = self.auth_config
166
167 self.validate_auth_config(config)
168
169 os_options = {}
170
171 os_options['region_name'] = config.get('auth_region')
172
173 try:
174 self.url, self.token = client.get_auth(
175 config.get('auth_url', ''),
176 config.get('auth_user', ''),
177 config.get('auth_password', ''),
178 auth_version=2,
179 tenant_name=config.get('auth_tenant_name', ''),
180 os_options=os_options,
181 )
182 except client.ClientException:
183 self.url = None
184 self.token = None
185
186 if self.url is None or self.token is None:
187 raise DataStoreException("Missing or invalid authentication info.")
188
189 self.auth_bits = (self.url, self.token, self.container)
190
191 def _create_container(self, container):165 def _create_container(self, container):
192 client.put_container(self.url, self.token, container)166 self.client.put_container(self.container_id)
193
194 def _get_container_url(self):
195 return "{}/{}".format(self.url, self.container)
196167
=== modified file 'ci-utils/ci_utils/tests/test_data_store.py'
--- ci-utils/ci_utils/tests/test_data_store.py 2014-03-10 22:25:00 +0000
+++ ci-utils/ci_utils/tests/test_data_store.py 2014-05-28 10:09:04 +0000
@@ -15,28 +15,30 @@
1515
16import unittest16import unittest
1717
18
18from ci_utils import data_store19from ci_utils import data_store
1920
20auth_config_valid = {
21 'auth_url': 'http://example.com',
22 'auth_user': 'user',
23 'auth_password': 'pass',
24 'auth_tenant_name': 'tenant',
25 'auth_region': 'region',
26}
27
28auth_config_invalid = {}
2921
30filename = 'myproject_1.0-1_source.changes'22filename = 'myproject_1.0-1_source.changes'
3123
3224
33class TestDataStore(unittest.TestCase):25class TestDataStoreConfig(unittest.TestCase):
26
34 def test_valid_auth_config(self):27 def test_valid_auth_config(self):
35 data_store.DataStore.validate_auth_config(auth_config_valid)28 data_store.DataStore.validate_auth_config({
29 'auth_url': 'http://example.com',
30 'auth_user': 'user',
31 'auth_password': 'pass',
32 'auth_tenant_name': 'tenant',
33 'auth_region': 'region',
34 })
3635
37 def test_invalid_auth_config(self):36 def test_invalid_auth_config(self):
38 with self.assertRaises(data_store.DataStoreException):37 with self.assertRaises(data_store.DataStoreException):
39 data_store.DataStore.validate_auth_config(auth_config_invalid)38 data_store.DataStore.validate_auth_config({})
39
40
41class TestDataStoreFileName(unittest.TestCase):
4042
41 def test_get_file_name(self):43 def test_get_file_name(self):
42 path = '/home/ubuntu/myproject/{}'.format(filename)44 path = '/home/ubuntu/myproject/{}'.format(filename)
@@ -53,5 +55,6 @@
53 resp = data_store._get_file_name(path)55 resp = data_store._get_file_name(path)
54 self.assertEquals(resp, filename)56 self.assertEquals(resp, filename)
5557
58
56if __name__ == "__main__":59if __name__ == "__main__":
57 unittest.main()60 unittest.main()
5861
=== modified file 'test_runner/tstrun/tests/test_data_store.py'
--- test_runner/tstrun/tests/test_data_store.py 2014-02-17 10:13:29 +0000
+++ test_runner/tstrun/tests/test_data_store.py 2014-05-28 10:09:04 +0000
@@ -14,6 +14,7 @@
14# along with this program. If not, see <http://www.gnu.org/licenses/>.14# along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16import errno16import errno
17import os
17import unittest18import unittest
1819
1920
@@ -78,12 +79,11 @@
78 def setUp(self):79 def setUp(self):
79 super(TestDataStore, self).setUp()80 super(TestDataStore, self).setUp()
80 fixtures.set_uniq_cwd(self)81 fixtures.set_uniq_cwd(self)
82 # We create a unique container to isolate ourselves
81 self.store = data_store.DataStore(83 self.store = data_store.DataStore(
82 'test-runner', tstrun.get_auth_config(),84 os.path.basename(self.uniq_dir),
83 # FIXME: We need a unique identifier or parallel tests (same tests85 tstrun.get_auth_config(), public=True)
84 # but different users) can fail -- vila 2014-02-0686 self.addCleanup(self.store.delete, recursive=True)
85 identifier='test', public=True)
86 self.addCleanup(self.store.clear)
8787
88 def test_store_created_empty(self):88 def test_store_created_empty(self):
89 self.assertEqual([], self.store.list_files())89 self.assertEqual([], self.store.list_files())

Subscribers

People subscribed via source and target branches