Skip to content

Commit b06a2e4

Browse files
Python 3.12+ compatibility (#216)
* [BREAKING] Bump Python to 3.12+ * [DOCS] Use Python 3.12/3.13/3.14 in the compatibility list * [CLEAN-UP] Remove six package * [CLEAN-UP] Remove pkg_resources references * [CLEAN-UP] Replace distutils with stdlib (shutil) and packaging equivalents * [DEPS] Upgrade ansible from 8.7.0 to 11.13.0 * [DEPS] Replace azure/msrestazure with azure-* modern packages * [DEPS] Upgrade himl from 0.18.0 to 0.20.0 * [DEPS] Migrate from python-consul to py-consul 1.7.1 * [DEPS] Upgrade urllib3 from 2.6.0 to 2.7.0 * [DEPS] Pin hashmerge to 0.2 and passgen to 1.1.1 * [DEPS] Upgrade awscli from 1.42.30 to 1.45.36 and boto3/botocore from 1.40.30 to 1.43.36 * [DEPS] Upgrade hvac from 1.2.1 to 2.4.0 * [DEPS] Remove kubernetes package (unused) * [DEPS] Update Dockerfile dependencies * [CLEAN-UP] removed dead code in azurerm.py * [CLEAN-UP] Remove dead code from parser (_check_args_for_unicode) * [CLEAN-UP] _check_args_for_unicode is not needed, as Python 3 already handles Unicode chars * [BUGFIX] Python 2 leftovers clean-up - Replace basestring with str - Drop .encode('utf-8') calls - Fix broken urllib import - Add explicit dependency on requests - fix error message retrieval - cleaned up object/super redundancy
1 parent a33a9ab commit b06a2e4

39 files changed

Lines changed: 159 additions & 263 deletions

Dockerfile

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
FROM python:3.12.3-alpine3.18 AS compile-image
22
ARG TARGETARCH
33
ARG TARGETPLATFORM
4-
ARG TERRAFORM_VERSION="0.12.31"
5-
ARG AZURE_CLI_VERSION="2.0.67"
4+
ARG TERRAFORM_VERSION="0.15.5"
5+
ARG AZURE_CLI_VERSION="2.87.0"
66

77
ENV BOTO_CONFIG=/dev/null
88
COPY . /sources/
@@ -40,10 +40,9 @@ RUN apk del --purge build
4040
FROM python:3.12.3-alpine3.18
4141
ARG TARGETARCH
4242
ARG TARGETPLATFORM
43-
ARG TERRAFORM_VERSION="0.12.31"
44-
ARG VAULT_VERSION="1.1.3"
45-
ARG KUBECTL_VERSION="v1.17.0"
46-
ARG AWS_IAM_AUTHENTICATOR_VERSION="1.13.7/2019-06-11"
43+
ARG TERRAFORM_VERSION="0.15.5"
44+
ARG VAULT_VERSION="2.0.3"
45+
ARG KUBECTL_VERSION="v1.34.1"
4746
ARG HELM_VERSION="v3.16.3"
4847
ARG HELM_FILE_VERSION="1.1.8"
4948
ARG HELM_DIFF_VERSION="2.11.0%2B5"
@@ -63,7 +62,7 @@ RUN adduser ops -Du 2342 -h /home/ops \
6362
&& ops --verbose -h \
6463
&& apk del --purge build
6564

66-
RUN wget -q https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/${TARGETARCH}/kubectl -O /usr/local/bin/kubectl \
65+
RUN wget -q https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${TARGETARCH}/kubectl -O /usr/local/bin/kubectl \
6766
&& chmod +x /usr/local/bin/kubectl
6867

6968
RUN wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-${TARGETARCH}.tar.gz -O - | tar -xzO linux-${TARGETARCH}/helm > /usr/local/bin/helm \
@@ -76,9 +75,6 @@ RUN wget -q -O terraform.zip https://releases.hashicorp.com/terraform/${TERRAFOR
7675
RUN wget -q -O vault.zip https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip \
7776
&& unzip vault.zip -d /usr/local/bin \
7877
&& rm -rf vault.zip
79-
80-
RUN wget -q https://amazon-eks.s3-us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERSION}/bin/linux/${TARGETARCH}/aws-iam-authenticator -O /usr/local/bin/aws-iam-authenticator \
81-
&& chmod +x /usr/local/bin/aws-iam-authenticator
8278

8379
RUN wget -q https://github.com/helmfile/helmfile/releases/download/v${HELM_FILE_VERSION}/helmfile_${HELM_FILE_VERSION}_linux_${TARGETARCH}.tar.gz -O - | tar -xzO helmfile > /usr/local/bin/helmfile \
8480
&& chmod +x /usr/local/bin/helmfile
@@ -94,7 +90,6 @@ WORKDIR /home/ops
9490
USER root
9591
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.9.11
9692
RUN helm plugin install https://github.com/jkroepke/helm-secrets --version v3.8.2
97-
RUN helm plugin install https://github.com/rimusz/helm-tiller # Obsolete in Helm 3
9893

9994

10095
COPY --from=compile-image /azure-cli /home/ops/.local/azure-cli

requirements.txt

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
simpledi==0.4.1
2-
awscli==1.42.30
3-
boto3==1.40.30
4-
botocore==1.40.30
5-
urllib3==2.6.0
6-
ansible==8.7.0
7-
azure-common==1.1.28
8-
azure==4.0.0
9-
msrestazure==0.6.4
2+
awscli==1.45.36
3+
boto3==1.43.36
4+
botocore==1.43.36
5+
urllib3==2.7.0
6+
ansible==11.13.0
7+
azure-identity==1.25.3
8+
azure-mgmt-compute==38.1.0
9+
azure-mgmt-network==30.2.0
10+
azure-mgmt-resource==26.0.0
1011
Jinja2==3.1.6
11-
hashmerge
12-
python-consul
13-
hvac==1.2.1
14-
passgen
12+
hashmerge==0.2
13+
py-consul==1.7.1
14+
requests==2.34.2
15+
hvac==2.4.0
16+
passgen==1.1.1
1517
inflection==0.5.1
16-
kubernetes==33.1.0
17-
himl==0.18.0
18-
six
18+
packaging==26.2
19+
himl==0.20.0
1920
GitPython==3.1.*

setup.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
import os
1212
import sys
1313

14-
try:
15-
from setuptools import setup, find_packages
16-
except ImportError:
17-
from distutils.core import setup, find_packages
14+
from setuptools import setup, find_packages
1815

1916
with open('README.md') as f:
2017
_readme = f.read()
@@ -28,7 +25,7 @@
2825
long_description=_readme + '\n\n',
2926
long_description_content_type='text/markdown',
3027
url='https://github.com/adobe/ops-cli',
31-
python_requires='>=3.5',
28+
python_requires='>=3.12',
3229
author='Adobe',
3330
author_email='noreply@adobe.com',
3431
license='Apache2',
@@ -39,9 +36,9 @@
3936
'License :: OSI Approved :: Apache Software License',
4037
'Operating System :: OS Independent',
4138
'Programming Language :: Python :: 3',
42-
'Programming Language :: Python :: 3.9',
43-
'Programming Language :: Python :: 3.10',
44-
'Programming Language :: Python :: 3.11',
39+
'Programming Language :: Python :: 3.12',
40+
'Programming Language :: Python :: 3.13',
41+
'Programming Language :: Python :: 3.14',
4542
'Programming Language :: Python :: Implementation :: CPython',
4643
'Programming Language :: Python :: Implementation :: PyPy',
4744
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',

src/ops/__init__.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,30 @@
88
# OF ANY KIND, either express or implied. See the License for the specific language
99
# governing permissions and limitations under the License.
1010

11-
import pkg_resources
1211
import re
13-
from distutils.version import StrictVersion
12+
from importlib.metadata import version as importlib_version
13+
from packaging.version import Version
1414
from subprocess import call, Popen, PIPE
1515

16-
from six import PY3
17-
1816
from .cli import display
1917

2018

2119
def validate_ops_version(min_ops_version):
22-
current_ops_version = [
23-
x.version for x in pkg_resources.working_set if x.project_name == "ops-cli"][0]
24-
if StrictVersion(current_ops_version) < StrictVersion(min_ops_version):
20+
current_ops_version = importlib_version('ops-cli')
21+
if Version(current_ops_version) < Version(min_ops_version):
2522
raise Exception("The current ops version {0} is lower than the minimum required version {1}. "
2623
"Please upgrade by following the instructions seen here: "
2724
"https://github.com/adobe/ops-cli#installing".format(current_ops_version, min_ops_version))
2825

2926

30-
class Executor(object):
27+
class Executor:
3128
""" All cli commands usually return a dict(command=...) that will be executed by this handler"""
3229

3330
def __call__(self, result, pass_trough=True, cwd=None):
3431
try:
3532
return self._execute(result, pass_trough, cwd)
3633
except Exception as ex:
37-
display(str(ex) if PY3 else ex.message, stderr=True, color='red')
34+
display(str(ex), stderr=True, color='red')
3835
display(
3936
'------- TRACEBACK ----------',
4037
stderr=True,

src/ops/ansible/filter_plugins/commonfilters.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
#OF ANY KIND, either express or implied. See the License for the specific language
99
#governing permissions and limitations under the License.
1010

11-
from __future__ import absolute_import
1211
import os
1312
from ops.cli import display
14-
from six import iteritems
15-
1613

1714
def read_file(fname):
1815
if os.path.exists(fname):
@@ -38,7 +35,7 @@ def read_consul(key_path, consul_url="http://localhost:8500", recurse=True, show
3835
ret = sc.get(key_path,recurse)
3936
except Exception as e:
4037
if show_error:
41-
ret['error'] = e.message
38+
ret['error'] = str(e)
4239
return ret
4340

4441
def read_envvar(varname, default=None):
@@ -53,7 +50,7 @@ def read_yaml(fname, show_error=False):
5350
ret = y.safe_load(f.read())
5451
except Exception as e:
5552
if show_error:
56-
ret['error'] = e.message
53+
ret['error'] = str(e)
5754
return ret
5855

5956
def flatten_tree(d, parent_key='', sep='/'):
@@ -100,7 +97,7 @@ def write_vault(
10097
namespace=None, mount_point=None, auto_prompt=auto_prompt)
10198
new_data = {}
10299
if isinstance(data, dict):
103-
for k,v in iteritems(data):
100+
for k, v in data.items():
104101
new_data[k] = str(v)
105102
elif key:
106103
new_data[key] = str(data)
@@ -141,7 +138,7 @@ def escape_json(input):
141138
return escaped[1:-1]
142139
return escaped
143140

144-
class FilterModule(object):
141+
class FilterModule:
145142

146143
def filters(self):
147144
return {

src/ops/ansible/vars_plugins/clusterconfig.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ class VarsModule(BaseVarsPlugin):
2525
def __init__(self, *args):
2626
""" constructor """
2727

28-
super(VarsModule, self).__init__(*args)
28+
super().__init__(*args)
2929

3030
logger.debug("Running plugin: %s with cluster config %s" % (__file__, os.environ['OPS_CLUSTER_CONFIG']))
3131

3232
app = AppContainer([os.environ['OPS_CLUSTER_CONFIG'], 'noop'])
3333
self.config = app.cluster_config.all()
3434

3535
def get_vars(self, loader, path, entities, cache=True):
36-
super(VarsModule, self).get_vars(loader, path, entities)
36+
super().get_vars(loader, path, entities)
3737
return self.config

src/ops/ansible/vars_plugins/opsconfig.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class VarsModule(BaseVarsPlugin):
2525
def __init__(self, *args):
2626
""" constructor """
2727

28-
super(VarsModule, self).__init__(*args)
28+
super().__init__(*args)
2929

3030
logger.debug("Running plugin: %s with cluster config %s" % (__file__, os.environ['OPS_CLUSTER_CONFIG']))
3131

@@ -37,5 +37,5 @@ def __init__(self, *args):
3737
})
3838

3939
def get_vars(self, loader, path, entities, cache=True):
40-
super(VarsModule, self).get_vars(loader, path, entities)
40+
super().get_vars(loader, path, entities)
4141
return self.config

src/ops/cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def get_config_value(config, key):
4040
return config[key]
4141
except KeyError as e:
4242
err("You must set the %s value in %s.yaml or in the cli as an extra variable: -e %s=value" %
43-
(e.message, config['cluster'], e.message))
43+
(str(e), config['cluster'], str(e)))
4444
sys.exit(1)
4545

4646
def check_if_teleport_binary_installed():

src/ops/cli/config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def load_extra_vars(loader):
6767
return extra_vars
6868

6969

70-
class ClusterConfig(object):
70+
class ClusterConfig:
7171
def __init__(self, cluster_config_generator,
7272
ops_config, cluster_config_path):
7373
"""
@@ -130,7 +130,7 @@ def load_ssh_keys(self, cluster_config_path):
130130
self.has_ssh_keys = False
131131

132132

133-
class JinjaConfigGenerator(object):
133+
class JinjaConfigGenerator:
134134
def __init__(self, console_args, cluster_config_path, template):
135135
self.cluster_config_path = cluster_config_path
136136
self.console_args = console_args
@@ -162,7 +162,7 @@ def get(self):
162162
return yaml.safe_load(rendered)
163163

164164

165-
class ClusterConfigGenerator(object):
165+
class ClusterConfigGenerator:
166166
def __init__(self, console_args, cluster_config_path, template):
167167
self.template = template
168168
self.cluster_config_path = cluster_config_path

src/ops/cli/config_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_epilog(self):
3232
'''
3333

3434

35-
class ConfigGeneratorRunner(object):
35+
class ConfigGeneratorRunner:
3636
def __init__(self, cluster_config_path):
3737
self.cluster_config_path = cluster_config_path
3838

0 commit comments

Comments
 (0)