Skip to content

Commit

Permalink
chore: setup pre-commit (#234)
Browse files Browse the repository at this point in the history
* chore: add pre-commit config

* chore: fix pre-commit errors

* chore: add black pre-commit hook

* style: format python files with black

* chore: add isort pre-commit hook

* style: format python files using isort

* chore: add pyupgrade pre-commit hook

* refactor: upgrade code to python3.7

* Allow stacking PRs

Co-authored-by: Julian Tölle <[email protected]>

---------

Co-authored-by: Julian Tölle <[email protected]>
  • Loading branch information
jooola and apricote authored Jun 27, 2023
1 parent e839975 commit dfff49e
Show file tree
Hide file tree
Showing 42 changed files with 905 additions and 1,092 deletions.
26 changes: 12 additions & 14 deletions .azure-pipelines/scripts/combine-coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
"""

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
import re
Expand All @@ -20,12 +18,12 @@ def main():
"""Main program entry point."""
source_directory = sys.argv[1]

if '/ansible_collections/' in os.getcwd():
if "/ansible_collections/" in os.getcwd():
output_path = "tests/output"
else:
output_path = "test/results"

destination_directory = os.path.join(output_path, 'coverage')
destination_directory = os.path.join(output_path, "coverage")

if not os.path.exists(destination_directory):
os.makedirs(destination_directory)
Expand All @@ -34,27 +32,27 @@ def main():
count = 0

for name in os.listdir(source_directory):
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
label = match.group('label')
attempt = int(match.group('attempt'))
match = re.search("^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$", name)
label = match.group("label")
attempt = int(match.group("attempt"))
jobs[label] = max(attempt, jobs.get(label, 0))

for label, attempt in jobs.items():
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
name = f"Coverage {attempt} {label}"
source = os.path.join(source_directory, name)
source_files = os.listdir(source)

for source_file in source_files:
source_path = os.path.join(source, source_file)
destination_path = os.path.join(destination_directory, source_file + '.' + label)
print('"%s" -> "%s"' % (source_path, destination_path))
destination_path = os.path.join(destination_directory, source_file + "." + label)
print(f'"{source_path}" -> "{destination_path}"')
shutil.copyfile(source_path, destination_path)
count += 1

print('Coverage file count: %d' % count)
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
print("Coverage file count: %d" % count)
print("##vso[task.setVariable variable=coverageFileCount]%d" % count)
print("##vso[task.setVariable variable=outputPath]%s" % output_path)


if __name__ == '__main__':
if __name__ == "__main__":
main()
10 changes: 4 additions & 6 deletions .azure-pipelines/scripts/time-command.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env python
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import sys
import time
Expand All @@ -12,14 +10,14 @@ def main():
"""Main program entry point."""
start = time.time()

sys.stdin.reconfigure(errors='surrogateescape')
sys.stdout.reconfigure(errors='surrogateescape')
sys.stdin.reconfigure(errors="surrogateescape")
sys.stdout.reconfigure(errors="surrogateescape")

for line in sys.stdin:
seconds = time.time() - start
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
sys.stdout.write("%02d:%02d %s" % (seconds // 60, seconds % 60, line))
sys.stdout.flush()


if __name__ == '__main__':
if __name__ == "__main__":
main()
23 changes: 23 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Lint

on:
push:
branches: [main]
pull_request:

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup python
uses: actions/setup-python@v4
with:
python-version: 3.x

- name: Install dependencies
run: pip install pre-commit

- name: Run pre-commit
run: pre-commit run --all-files --show-diff-on-failure
11 changes: 11 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
stages:
- lint
- sanity
- integration

Expand All @@ -8,6 +9,16 @@ variables:
default:
image: python:$PYTHON_VERSION

pre-commit:
stage: lint

image: python:3.11-alpine
before_script:
- apk add build-base git
- pip install pre-commit
script:
- pre-commit run --all-files --show-diff-on-failure

sanity:
stage: sanity
allow_failure: true
Expand Down
43 changes: 43 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-symlinks
- id: destroyed-symlinks

- id: check-json
- id: check-yaml
- id: check-toml

- id: check-merge-conflict
- id: end-of-file-fixer
- id: mixed-line-ending
- id: trailing-whitespace

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
files: \.(md|ya?ml)$
exclude: ^changelogs/changelog.yaml$

- repo: https://github.com/asottile/pyupgrade
rev: v3.7.0
hooks:
- id: pyupgrade
args: [--py37-plus]

- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort

- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
10 changes: 3 additions & 7 deletions plugins/doc_fragments/hcloud.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, Hetzner Cloud GmbH <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function

__metaclass__ = type


class ModuleDocFragment(object):
DOCUMENTATION = '''
class ModuleDocFragment:
DOCUMENTATION = """
options:
api_token:
description:
Expand All @@ -26,4 +22,4 @@ class ModuleDocFragment(object):
- name: Documentation for Hetzner Cloud API
description: Complete reference for the Hetzner Cloud API.
link: https://docs.hetzner.cloud/
'''
"""
70 changes: 36 additions & 34 deletions plugins/inventory/hcloud.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# Copyright (c) 2019 Hetzner Cloud GmbH <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)

__metaclass__ = type

DOCUMENTATION = r'''
DOCUMENTATION = r"""
name: hcloud
author:
- Lukas Kaemmerling (@lkaemmerling)
Expand Down Expand Up @@ -84,7 +81,7 @@
type: list
elements: str
required: false
'''
"""

EXAMPLES = r"""
# Minimal example. `HCLOUD_TOKEN` is exposed in environment.
Expand Down Expand Up @@ -118,27 +115,30 @@
"""

import os
from ipaddress import IPv6Network

from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
from ansible.release import __version__
from ipaddress import IPv6Network

try:
from hcloud import hcloud
from hcloud import APIException
from hcloud import APIException, hcloud

HAS_HCLOUD = True
except ImportError:
HAS_HCLOUD = False


class InventoryModule(BaseInventoryPlugin, Constructable):
NAME = 'hetzner.hcloud.hcloud'
NAME = "hetzner.hcloud.hcloud"

def _configure_hcloud_client(self):
self.token_env = self.get_option("token_env")
self.templar.available_variables = self._vars
self.api_token = self.templar.template(self.get_option("token"), fail_on_undefined=False) or os.getenv(self.token_env)
self.api_token = self.templar.template(self.get_option("token"), fail_on_undefined=False) or os.getenv(
self.token_env
)
if self.api_token is None:
raise AnsibleError(
"Please specify a token, via the option token, via environment variable HCLOUD_TOKEN "
Expand All @@ -147,10 +147,12 @@ def _configure_hcloud_client(self):

self.endpoint = os.getenv("HCLOUD_ENDPOINT") or "https://api.hetzner.cloud/v1"

self.client = hcloud.Client(token=self.api_token,
api_endpoint=self.endpoint,
application_name="ansible-inventory",
application_version=__version__)
self.client = hcloud.Client(
token=self.api_token,
api_endpoint=self.endpoint,
application_name="ansible-inventory",
application_version=__version__,
)

def _test_hcloud_token(self):
try:
Expand All @@ -168,14 +170,15 @@ def _get_servers(self):

def _filter_servers(self):
if self.get_option("network"):
network = self.templar.template(self.get_option("network"), fail_on_undefined=False) or self.get_option("network")
network = self.templar.template(self.get_option("network"), fail_on_undefined=False) or self.get_option(
"network"
)
try:
self.network = self.client.networks.get_by_name(network)
if self.network is None:
self.network = self.client.networks.get_by_id(network)
except APIException:
raise AnsibleError(
"The given network is not found.")
raise AnsibleError("The given network is not found.")

tmp = []
for server in self.servers:
Expand Down Expand Up @@ -225,16 +228,17 @@ def _set_server_attributes(self, server):

if server.public_net.ipv6:
self.inventory.set_variable(server.name, "ipv6_network", to_native(server.public_net.ipv6.network))
self.inventory.set_variable(server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask))
self.inventory.set_variable(server.name, "ipv6", to_native(self._first_ipv6_address(server.public_net.ipv6.ip)))
self.inventory.set_variable(
server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask)
)
self.inventory.set_variable(
server.name, "ipv6", to_native(self._first_ipv6_address(server.public_net.ipv6.ip))
)

self.inventory.set_variable(
server.name,
"private_networks",
[
{"name": n.network.name, "id": n.network.id, "ip": n.ip}
for n in server.private_net
],
[{"name": n.network.name, "id": n.network.id, "ip": n.ip} for n in server.private_net],
)

if self.get_option("network"):
Expand Down Expand Up @@ -306,21 +310,17 @@ def _get_server_ansible_host(self, server):
return to_native(server_private_network.ip)

else:
raise AnsibleError(
"You can only connect via private IPv4 if you specify a network")
raise AnsibleError("You can only connect via private IPv4 if you specify a network")

def _first_ipv6_address(self, network):
return next(IPv6Network(network).hosts())

def verify_file(self, path):
"""Return the possibly of a file being consumable by this plugin."""
return (
super(InventoryModule, self).verify_file(path) and
path.endswith(("hcloud.yaml", "hcloud.yml"))
)
return super().verify_file(path) and path.endswith(("hcloud.yaml", "hcloud.yml"))

def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path, cache)
super().parse(inventory, loader, path, cache)

if not HAS_HCLOUD:
raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires hcloud-python.")
Expand All @@ -339,13 +339,15 @@ def parse(self, inventory, loader, path, cache=True):
self._set_server_attributes(server)

# Use constructed if applicable
strict = self.get_option('strict')
strict = self.get_option("strict")

# Composed variables
self._set_composite_vars(self.get_option('compose'), self.inventory.get_host(server.name).get_vars(), server.name, strict=strict)
self._set_composite_vars(
self.get_option("compose"), self.inventory.get_host(server.name).get_vars(), server.name, strict=strict
)

# Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group
self._add_host_to_composed_groups(self.get_option('groups'), {}, server.name, strict=strict)
self._add_host_to_composed_groups(self.get_option("groups"), {}, server.name, strict=strict)

# Create groups based on variable values and add the corresponding hosts to it
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), {}, server.name, strict=strict)
self._add_host_to_keyed_groups(self.get_option("keyed_groups"), {}, server.name, strict=strict)
6 changes: 1 addition & 5 deletions plugins/module_utils/hcloud.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, Hetzner Cloud GmbH <[email protected]>

# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

from ansible.module_utils.ansible_release import __version__
from ansible.module_utils.basic import env_fallback, missing_required_lib
Expand All @@ -18,7 +14,7 @@
HAS_HCLOUD = False


class Hcloud(object):
class Hcloud:
def __init__(self, module, represent):
self.module = module
self.represent = represent
Expand Down
Loading

0 comments on commit dfff49e

Please sign in to comment.