Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add python warning if install a pack that only supports python 2 #5037

Merged
merged 12 commits into from
Sep 16, 2020
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Added
default pass to screen when the script completes. (improvement) #5013

Contributed by @punkrokk
* Added deprecation warning if attempt to install or download a pack that only supports
Python 2.
amanda11 marked this conversation as resolved.
Show resolved Hide resolved

Contributed by @amanda11

Changed
~~~~~~~
Expand Down
15 changes: 15 additions & 0 deletions contrib/packs/actions/get_pack_warnings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


---
name: "get_pack_warnings"
runner_type: "python-script"
description: "Get pack warnings specified in pack.yaml"
enabled: true
pack: packs
entry_point: "pack_mgmt/get_pack_warnings.py"
parameters:
packs_status:
type: object
description: Dictionary of pack name to download status.
required: true
default: null
59 changes: 59 additions & 0 deletions contrib/packs/actions/pack_mgmt/get_pack_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2020 The StackStorm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function

import six

from st2common.content.utils import get_pack_base_path
from st2common.runners.base_action import Action
from st2common.util.pack import get_pack_metadata
from st2common.util.pack import get_pack_warnings


class GetPackWarnings(Action):
def run(self, packs_status):
"""
:param packs_status: Name of the pack and download status.
:type: packs_status: ``dict``
"""
result = {}
warning_list = []

if not packs_status:
return result

for pack, status in six.iteritems(packs_status):
if 'success' not in status.lower():
continue

warning = get_warnings(pack)

if warning:
warning_list.append(warning)

result['warning_list'] = warning_list

return result


def get_warnings(pack=None):
result = None
pack_path = get_pack_base_path(pack)
try:
pack_metadata = get_pack_metadata(pack_dir=pack_path)
result = get_pack_warnings(pack_metadata)
except Exception:
print('Could not open pack.yaml at location %s' % pack_path)
finally:
return result
12 changes: 12 additions & 0 deletions contrib/packs/actions/workflows/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ vars:
- packs_list: null
- dependency_list: null
- conflict_list: null
- warning_list: null
- nested: 10
- message: ""

Expand Down Expand Up @@ -99,6 +100,16 @@ tasks:
python3: <% ctx().python3 %>
next:
- when: <% succeeded() %>
do: get_pack_warnings

get_pack_warnings:
action: packs.get_pack_warnings
input:
packs_status: <% task(download_pack).result.result %>
next:
- when: <% succeeded() %>
publish:
- warning_list: <% result().result.warning_list %>
do: register_pack

register_pack:
Expand All @@ -114,3 +125,4 @@ output:
- packs_list: <% ctx().packs_list %>
- message: <% ctx().message %>
- conflict_list: <% ctx().conflict_list %>
- warning_list: <% ctx().warning_list %>
154 changes: 154 additions & 0 deletions contrib/packs/tests/test_get_pack_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env python

# Copyright 2020 The StackStorm Authors.
# Copyright 2019 Extreme Networks, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import mock

from st2tests.base import BaseActionTestCase

from pack_mgmt.get_pack_warnings import GetPackWarnings

PACK_METADATA = {
# Python 2 & 3
"py23": {
"version": "0.4.0",
"name": "py23",
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
"author": "st2-dev",
"keywords": ["some", "search", "another", "terms"],
"email": "info@stackstorm.com",
"description": "st2 pack to test package management pipeline",
"python_versions": ["2","3"],
},
# Python 3
"py3": {
"version": "0.4.0",
"name": "py3",
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
"author": "st2-dev",
"keywords": ["some", "search", "another", "terms"],
"email": "info@stackstorm.com",
"description": "st2 pack to test package management pipeline",
"python_versions": ["3"],
},
# Python missing
"pynone": {
"version": "0.4.0",
"name": "pynone",
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-no_warnings",
"author": "st2-dev",
"keywords": ["some", "search", "another", "terms"],
"email": "info@stackstorm.com",
"description": "st2 pack to test package management pipeline",
},
# Python 2 only
"py2": {
"version": "0.5.0",
"name": "py2",
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-test2",
"author": "stanley",
"keywords": ["some", "special", "terms"],
"email": "info@stackstorm.com",
"description": "another st2 pack to test package management pipeline",
"python_versions": ["2"],
},
# Python 2 only
"py22": {
"version": "0.5.0",
"name": "py22",
"repo_url": "https://github.com/StackStorm-Exchange/stackstorm-test2",
"author": "stanley",
"keywords": ["some", "special", "terms"],
"email": "info@stackstorm.com",
"description": "another st2 pack to test package management pipeline",
"python_versions": ["2"]
}
}

def mock_get_pack_basepath(pack):
"""
Mock get_pack_basepath function which just returns pack n ame
"""
return pack


def mock_get_pack_metadata(pack_dir):
"""
Mock get_pack_version function which return mocked pack version
"""
metadata = {}

if pack_dir in PACK_METADATA:
metadata = PACK_METADATA[pack_dir]
return metadata


@mock.patch('pack_mgmt.get_pack_warnings.get_pack_base_path', mock_get_pack_basepath)
@mock.patch('pack_mgmt.get_pack_warnings.get_pack_metadata', mock_get_pack_metadata)
class GetPackWarningsTestCase(BaseActionTestCase):
action_cls = GetPackWarnings

def setUp(self):
super(GetPackWarningsTestCase, self).setUp()

def test_run_get_pack_warnings_py3_pack(self):
action = self.get_action_instance()
packs_status = {"py3": "Success."}

result = action.run(packs_status=packs_status)
self.assertEqual(result['warning_list'], [])

def test_run_get_pack_warnings_py2_pack(self):
action = self.get_action_instance()
packs_status = {"py2": "Success."}

result = action.run(packs_status=packs_status)
self.assertEqual(len(result['warning_list']), 1)
warning = result['warning_list'][0]
self.assertTrue("DEPRECATION WARNING" in warning)
self.assertTrue("Pack py2 only supports Python 2" in warning)

def test_run_get_pack_warnings_py23_pack(self):
action = self.get_action_instance()
packs_status = {"py23": "Success."}

result = action.run(packs_status=packs_status)
self.assertEqual(result['warning_list'], [])

def test_run_get_pack_warnings_pynone_pack(self):
action = self.get_action_instance()
packs_status = {"pynone": "Success."}

result = action.run(packs_status=packs_status)
self.assertEqual(result['warning_list'], [])

def test_run_get_pack_warnings_multiple_pack(self):
action = self.get_action_instance()
packs_status = {"py2": "Success.",
"py23": "Success.",
"py22": "Success."}

result = action.run(packs_status=packs_status)
self.assertEqual(len(result['warning_list']), 2)
warning0 = result['warning_list'][0]
warning1 = result['warning_list'][1]
self.assertTrue("DEPRECATION WARNING" in warning0)
self.assertTrue("DEPRECATION WARNING" in warning1)
self.assertTrue(("Pack py2 only supports Python 2" in warning0 and
"Pack py22 only supports Python 2" in warning1) or
("Pack py22 only supports Python 2" in warning0 and
"Pack py2 only supports Python 2" in warning1))

4 changes: 4 additions & 0 deletions st2client/st2client/commands/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ def run_and_print(self, args, **kwargs):
attributes=args.attr, widths=args.width,
json=args.json, yaml=args.yaml)

warnings = instance.result['output']['warning_list']
for warning in warnings:
print(warning)


class PackRemoveCommand(PackAsyncCommand):
def __init__(self, resource, *args, **kwargs):
Expand Down
20 changes: 20 additions & 0 deletions st2common/st2common/util/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
__all__ = [
'get_pack_ref_from_metadata',
'get_pack_metadata',
'get_pack_warnings',

'get_pack_common_libs_path_for_pack_ref',
'get_pack_common_libs_path_for_pack_db',
Expand All @@ -41,6 +42,11 @@
'normalize_pack_version'
]

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


def get_pack_ref_from_metadata(metadata, pack_directory_name=None):
"""
Expand Down Expand Up @@ -94,6 +100,20 @@ def get_pack_metadata(pack_dir):
return content


def get_pack_warnings(pack_metadata):
"""
Return warning string if pack metadata indicates only python 2 is supported

:rtype: ``str``
"""
warning = None
versions = pack_metadata.get('python_versions', None)
pack_name = pack_metadata.get('name', None)
if versions and set(versions) == set(['2']):
warning = PACK_PYTHON2_WARNING % pack_name
return warning


def validate_config_against_schema(config_schema, config_object, config_path,
pack_name=None):
"""
Expand Down
20 changes: 14 additions & 6 deletions st2common/st2common/util/pack_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from st2common.services.packs import get_pack_from_index
from st2common.util.pack import get_pack_metadata
from st2common.util.pack import get_pack_ref_from_metadata
from st2common.util.pack import get_pack_warnings
from st2common.util.green import shell
from st2common.util.versioning import complex_semver_match
from st2common.util.versioning import get_stackstorm_version
Expand Down Expand Up @@ -155,16 +156,18 @@ def download_pack(pack, abs_repo_base='/opt/stackstorm/packs', verify_ssl=True,
clone_repo(temp_dir=abs_local_path, repo_url=pack_url, verify_ssl=verify_ssl,
ref=pack_version)

pack_metadata = get_pack_metadata(pack_dir=abs_local_path)
pack_ref = get_pack_ref(pack_dir=abs_local_path)
result[1] = pack_ref

# 2. Verify that the pack version if compatible with current StackStorm version
if not force:
verify_pack_version(pack_dir=abs_local_path, use_python3=use_python3)
verify_pack_version(pack_metadata=pack_metadata, use_python3=use_python3)

# 3. Move pack to the final location
move_result = move_pack(abs_repo_base=abs_repo_base, pack_name=pack_ref,
abs_local_path=abs_local_path,
pack_metadata=pack_metadata,
force_owner_group=force_owner_group,
force_permissions=force_permissions,
logger=logger)
Expand Down Expand Up @@ -267,7 +270,7 @@ def clone_repo(temp_dir, repo_url, verify_ssl=True, ref='master'):
return temp_dir


def move_pack(abs_repo_base, pack_name, abs_local_path, force_owner_group=True,
def move_pack(abs_repo_base, pack_name, abs_local_path, pack_metadata, force_owner_group=True,
force_permissions=True, logger=LOG):
"""
Move pack directory into the final location.
Expand Down Expand Up @@ -302,7 +305,12 @@ def move_pack(abs_repo_base, pack_name, abs_local_path, force_owner_group=True,
# 2. Setup the right permissions and group ownership
apply_pack_permissions(pack_path=dest_pack_path)

message = 'Success.'
# Log warning if python2 only supported
warning = get_pack_warnings(pack_metadata)
if warning:
logger.warning(warning)

message = "Success."
elif message:
message = 'Failure : %s' % message

Expand Down Expand Up @@ -420,11 +428,10 @@ def is_desired_pack(abs_pack_path, pack_name):
return (True, '')


def verify_pack_version(pack_dir, use_python3=False):
def verify_pack_version(pack_metadata, use_python3=False):
"""
Verify that the pack works with the currently running StackStorm version.
"""
pack_metadata = get_pack_metadata(pack_dir=pack_dir)
pack_name = pack_metadata.get('name', None)
required_stackstorm_version = pack_metadata.get('stackstorm_version', None)
supported_python_versions = pack_metadata.get('python_versions', None)
Expand Down Expand Up @@ -456,7 +463,8 @@ def verify_pack_version(pack_dir, use_python3=False):
'the pack is not guaranteed to work.' % (pack_name, CURRENT_PYTHON_VERSION))
raise ValueError(msg)
else:
# Pack support Python 2.x and 3.x so no check is needed
# Pack support Python 2.x and 3.x so no check is needed, or
# supported version matches ST2 version
pass

return True
Expand Down
Loading