Skip to content

Commit f17e0b0

Browse files
authored
Merge pull request #5037 from StackStorm/add_python_warning_pack_install
Add python warning if install a pack that only supports python 2
2 parents eb9c906 + 3f3326e commit f17e0b0

File tree

9 files changed

+308
-5
lines changed

9 files changed

+308
-5
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Added
1919
default pass to screen when the script completes. (improvement) #5013
2020

2121
Contributed by @punkrokk
22+
* Added deprecation warning if attempt to install or download a pack that only supports
23+
Python 2. (new feature) #5037
24+
25+
Contributed by @amanda11
2226

2327
Changed
2428
~~~~~~~
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: "get_pack_warnings"
3+
runner_type: "python-script"
4+
description: "Get pack warnings from analysing pack.yaml"
5+
enabled: true
6+
pack: packs
7+
entry_point: "pack_mgmt/get_pack_warnings.py"
8+
parameters:
9+
packs_status:
10+
type: object
11+
description: Dictionary of pack name to download status.
12+
required: true
13+
default: null
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2020 The StackStorm Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain 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,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from __future__ import print_function
15+
16+
import six
17+
18+
from st2common.content.utils import get_pack_base_path
19+
from st2common.runners.base_action import Action
20+
from st2common.util.pack import get_pack_metadata
21+
from st2common.util.pack import get_pack_warnings
22+
23+
24+
class GetPackWarnings(Action):
25+
def run(self, packs_status):
26+
"""
27+
:param packs_status: Name of the pack and download status.
28+
:type: packs_status: ``dict``
29+
"""
30+
result = {}
31+
warning_list = []
32+
33+
if not packs_status:
34+
return result
35+
36+
for pack, status in six.iteritems(packs_status):
37+
if 'success' not in status.lower():
38+
continue
39+
40+
warning = get_warnings(pack)
41+
42+
if warning:
43+
warning_list.append(warning)
44+
45+
result['warning_list'] = warning_list
46+
47+
return result
48+
49+
50+
def get_warnings(pack=None):
51+
result = None
52+
pack_path = get_pack_base_path(pack)
53+
try:
54+
pack_metadata = get_pack_metadata(pack_dir=pack_path)
55+
result = get_pack_warnings(pack_metadata)
56+
except Exception:
57+
print('Could not open pack.yaml at location %s' % pack_path)
58+
finally:
59+
return result

contrib/packs/actions/workflows/install.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ vars:
1414
- packs_list: null
1515
- dependency_list: null
1616
- conflict_list: null
17+
- warning_list: null
1718
- nested: 10
1819
- message: ""
1920

@@ -99,6 +100,16 @@ tasks:
99100
python3: <% ctx().python3 %>
100101
next:
101102
- when: <% succeeded() %>
103+
do: get_pack_warnings
104+
105+
get_pack_warnings:
106+
action: packs.get_pack_warnings
107+
input:
108+
packs_status: <% task(download_pack).result.result %>
109+
next:
110+
- when: <% succeeded() %>
111+
publish:
112+
- warning_list: <% result().result.warning_list %>
102113
do: register_pack
103114

104115
register_pack:
@@ -114,3 +125,4 @@ output:
114125
- packs_list: <% ctx().packs_list %>
115126
- message: <% ctx().message %>
116127
- conflict_list: <% ctx().conflict_list %>
128+
- warning_list: <% ctx().warning_list %>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2020 The StackStorm Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import mock
18+
19+
from st2tests.base import BaseActionTestCase
20+
from pack_mgmt.get_pack_warnings import GetPackWarnings
21+
22+
PACK_METADATA = {
23+
# Python 2 & 3
24+
"py23": {
25+
"version": "0.4.0",
26+
"name": "py23",
27+
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
28+
"author": "st2-dev",
29+
"keywords": ["some", "search", "another", "terms"],
30+
"email": "info@stackstorm.com",
31+
"description": "st2 pack to test package management pipeline",
32+
"python_versions": ["2","3"],
33+
},
34+
# Python 3
35+
"py3": {
36+
"version": "0.4.0",
37+
"name": "py3",
38+
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
39+
"author": "st2-dev",
40+
"keywords": ["some", "search", "another", "terms"],
41+
"email": "info@stackstorm.com",
42+
"description": "st2 pack to test package management pipeline",
43+
"python_versions": ["3"],
44+
},
45+
# Python missing
46+
"pynone": {
47+
"version": "0.4.0",
48+
"name": "pynone",
49+
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
50+
"author": "st2-dev",
51+
"keywords": ["some", "search", "another", "terms"],
52+
"email": "info@stackstorm.com",
53+
"description": "st2 pack to test package management pipeline",
54+
},
55+
# Python 2 only
56+
"py2": {
57+
"version": "0.5.0",
58+
"name": "py2",
59+
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-test2",
60+
"author": "stanley",
61+
"keywords": ["some", "special", "terms"],
62+
"email": "info@stackstorm.com",
63+
"description": "another st2 pack to test package management pipeline",
64+
"python_versions": ["2"],
65+
},
66+
# Python 2 only
67+
"py22": {
68+
"version": "0.5.0",
69+
"name": "py22",
70+
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-test2",
71+
"author": "stanley",
72+
"keywords": ["some", "special", "terms"],
73+
"email": "info@stackstorm.com",
74+
"description": "another st2 pack to test package management pipeline",
75+
"python_versions": ["2"]
76+
}
77+
}
78+
79+
def mock_get_pack_basepath(pack):
80+
"""
81+
Mock get_pack_basepath function which just returns pack n ame
82+
"""
83+
return pack
84+
85+
86+
def mock_get_pack_metadata(pack_dir):
87+
"""
88+
Mock get_pack_version function which return mocked pack version
89+
"""
90+
metadata = {}
91+
92+
if pack_dir in PACK_METADATA:
93+
metadata = PACK_METADATA[pack_dir]
94+
return metadata
95+
96+
97+
@mock.patch('pack_mgmt.get_pack_warnings.get_pack_base_path', mock_get_pack_basepath)
98+
@mock.patch('pack_mgmt.get_pack_warnings.get_pack_metadata', mock_get_pack_metadata)
99+
class GetPackWarningsTestCase(BaseActionTestCase):
100+
action_cls = GetPackWarnings
101+
102+
def setUp(self):
103+
super(GetPackWarningsTestCase, self).setUp()
104+
105+
def test_run_get_pack_warnings_py3_pack(self):
106+
action = self.get_action_instance()
107+
packs_status = {"py3": "Success."}
108+
109+
result = action.run(packs_status=packs_status)
110+
self.assertEqual(result['warning_list'], [])
111+
112+
def test_run_get_pack_warnings_py2_pack(self):
113+
action = self.get_action_instance()
114+
packs_status = {"py2": "Success."}
115+
116+
result = action.run(packs_status=packs_status)
117+
self.assertEqual(len(result['warning_list']), 1)
118+
warning = result['warning_list'][0]
119+
self.assertTrue("DEPRECATION WARNING" in warning)
120+
self.assertTrue("Pack py2 only supports Python 2" in warning)
121+
122+
def test_run_get_pack_warnings_py23_pack(self):
123+
action = self.get_action_instance()
124+
packs_status = {"py23": "Success."}
125+
126+
result = action.run(packs_status=packs_status)
127+
self.assertEqual(result['warning_list'], [])
128+
129+
def test_run_get_pack_warnings_pynone_pack(self):
130+
action = self.get_action_instance()
131+
packs_status = {"pynone": "Success."}
132+
133+
result = action.run(packs_status=packs_status)
134+
self.assertEqual(result['warning_list'], [])
135+
136+
def test_run_get_pack_warnings_multiple_pack(self):
137+
action = self.get_action_instance()
138+
packs_status = {"py2": "Success.",
139+
"py23": "Success.",
140+
"py22": "Success."}
141+
142+
result = action.run(packs_status=packs_status)
143+
self.assertEqual(len(result['warning_list']), 2)
144+
warning0 = result['warning_list'][0]
145+
warning1 = result['warning_list'][1]
146+
self.assertTrue("DEPRECATION WARNING" in warning0)
147+
self.assertTrue("DEPRECATION WARNING" in warning1)
148+
self.assertTrue(("Pack py2 only supports Python 2" in warning0 and
149+
"Pack py22 only supports Python 2" in warning1) or
150+
("Pack py22 only supports Python 2" in warning0 and
151+
"Pack py2 only supports Python 2" in warning1))

st2client/st2client/commands/pack.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ def run_and_print(self, args, **kwargs):
284284
attributes=args.attr, widths=args.width,
285285
json=args.json, yaml=args.yaml)
286286

287+
warnings = instance.result['output']['warning_list']
288+
for warning in warnings:
289+
print(warning)
290+
287291

288292
class PackRemoveCommand(PackAsyncCommand):
289293
def __init__(self, resource, *args, **kwargs):

st2common/st2common/util/pack.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
__all__ = [
3333
'get_pack_ref_from_metadata',
3434
'get_pack_metadata',
35+
'get_pack_warnings',
3536

3637
'get_pack_common_libs_path_for_pack_ref',
3738
'get_pack_common_libs_path_for_pack_db',
@@ -41,6 +42,11 @@
4142
'normalize_pack_version'
4243
]
4344

45+
# Common format for python 2.7 warning
46+
PACK_PYTHON2_WARNING = "DEPRECATION WARNING: Pack %s only supports Python 2.x. " \
47+
"Python 2 support will be dropped in future releases. " \
48+
"Please consider updating your packs to work with Python 3.x"
49+
4450

4551
def get_pack_ref_from_metadata(metadata, pack_directory_name=None):
4652
"""
@@ -94,6 +100,20 @@ def get_pack_metadata(pack_dir):
94100
return content
95101

96102

103+
def get_pack_warnings(pack_metadata):
104+
"""
105+
Return warning string if pack metadata indicates only python 2 is supported
106+
107+
:rtype: ``str``
108+
"""
109+
warning = None
110+
versions = pack_metadata.get('python_versions', None)
111+
pack_name = pack_metadata.get('name', None)
112+
if versions and set(versions) == set(['2']):
113+
warning = PACK_PYTHON2_WARNING % pack_name
114+
return warning
115+
116+
97117
def validate_config_against_schema(config_schema, config_object, config_path,
98118
pack_name=None):
99119
"""

st2common/st2common/util/pack_management.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from st2common.services.packs import get_pack_from_index
4343
from st2common.util.pack import get_pack_metadata
4444
from st2common.util.pack import get_pack_ref_from_metadata
45+
from st2common.util.pack import get_pack_warnings
4546
from st2common.util.green import shell
4647
from st2common.util.versioning import complex_semver_match
4748
from st2common.util.versioning import get_stackstorm_version
@@ -155,16 +156,18 @@ def download_pack(pack, abs_repo_base='/opt/stackstorm/packs', verify_ssl=True,
155156
clone_repo(temp_dir=abs_local_path, repo_url=pack_url, verify_ssl=verify_ssl,
156157
ref=pack_version)
157158

159+
pack_metadata = get_pack_metadata(pack_dir=abs_local_path)
158160
pack_ref = get_pack_ref(pack_dir=abs_local_path)
159161
result[1] = pack_ref
160162

161163
# 2. Verify that the pack version if compatible with current StackStorm version
162164
if not force:
163-
verify_pack_version(pack_dir=abs_local_path, use_python3=use_python3)
165+
verify_pack_version(pack_metadata=pack_metadata, use_python3=use_python3)
164166

165167
# 3. Move pack to the final location
166168
move_result = move_pack(abs_repo_base=abs_repo_base, pack_name=pack_ref,
167169
abs_local_path=abs_local_path,
170+
pack_metadata=pack_metadata,
168171
force_owner_group=force_owner_group,
169172
force_permissions=force_permissions,
170173
logger=logger)
@@ -267,7 +270,7 @@ def clone_repo(temp_dir, repo_url, verify_ssl=True, ref='master'):
267270
return temp_dir
268271

269272

270-
def move_pack(abs_repo_base, pack_name, abs_local_path, force_owner_group=True,
273+
def move_pack(abs_repo_base, pack_name, abs_local_path, pack_metadata, force_owner_group=True,
271274
force_permissions=True, logger=LOG):
272275
"""
273276
Move pack directory into the final location.
@@ -302,6 +305,11 @@ def move_pack(abs_repo_base, pack_name, abs_local_path, force_owner_group=True,
302305
# 2. Setup the right permissions and group ownership
303306
apply_pack_permissions(pack_path=dest_pack_path)
304307

308+
# Log warning if python2 only supported
309+
warning = get_pack_warnings(pack_metadata)
310+
if warning:
311+
logger.warning(warning)
312+
305313
message = 'Success.'
306314
elif message:
307315
message = 'Failure : %s' % message
@@ -420,11 +428,10 @@ def is_desired_pack(abs_pack_path, pack_name):
420428
return (True, '')
421429

422430

423-
def verify_pack_version(pack_dir, use_python3=False):
431+
def verify_pack_version(pack_metadata, use_python3=False):
424432
"""
425433
Verify that the pack works with the currently running StackStorm version.
426434
"""
427-
pack_metadata = get_pack_metadata(pack_dir=pack_dir)
428435
pack_name = pack_metadata.get('name', None)
429436
required_stackstorm_version = pack_metadata.get('stackstorm_version', None)
430437
supported_python_versions = pack_metadata.get('python_versions', None)
@@ -456,7 +463,8 @@ def verify_pack_version(pack_dir, use_python3=False):
456463
'the pack is not guaranteed to work.' % (pack_name, CURRENT_PYTHON_VERSION))
457464
raise ValueError(msg)
458465
else:
459-
# Pack support Python 2.x and 3.x so no check is needed
466+
# Pack support Python 2.x and 3.x so no check is needed, or
467+
# supported version matches ST2 version
460468
pass
461469

462470
return True

0 commit comments

Comments
 (0)