generated from ansible-collections/collection_template
-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d8cef6c
commit 9e2c31f
Showing
7 changed files
with
285 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
minor_changes: | ||
- "docker_container - implement better ``platform`` string comparisons to improve idempotency (https://github.com/ansible-collections/community.docker/issues/654, https://github.com/ansible-collections/community.docker/pull/705)." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
# This code is part of the Ansible collection community.docker, but is an independent component. | ||
# This particular file, and this file only, is based on containerd's platforms Go module | ||
# (https://github.com/containerd/containerd/tree/main/platforms) | ||
# | ||
# Copyright (c) 2023 Felix Fontein <[email protected]> | ||
# Copyright The containerd Authors | ||
# | ||
# It is licensed under the Apache 2.0 license (see LICENSES/Apache-2.0.txt in this collection) | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from __future__ import (absolute_import, division, print_function) | ||
__metaclass__ = type | ||
|
||
import re | ||
|
||
|
||
_VALID_STR = re.compile('^[A-Za-z0-9_-]+$') | ||
|
||
|
||
def _validate_part(string, part, part_name): | ||
if not part: | ||
raise ValueError('Invalid platform string "{string}": {part} is empty'.format(string=string, part=part_name)) | ||
if not _VALID_STR.match(part): | ||
raise ValueError('Invalid platform string "{string}": {part} has invalid characters'.format(string=string, part=part_name)) | ||
return part | ||
|
||
|
||
# See https://github.com/containerd/containerd/blob/main/platforms/database.go#L32-L38 | ||
_KNOWN_OS = ( | ||
"aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "ios", "js", | ||
"linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos", | ||
) | ||
|
||
# See https://github.com/containerd/containerd/blob/main/platforms/database.go#L54-L60 | ||
_KNOWN_ARCH = ( | ||
"386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", | ||
"loong64", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", | ||
"ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm", | ||
) | ||
|
||
|
||
def _normalize_os(os_str): | ||
# See normalizeOS() in https://github.com/containerd/containerd/blob/main/platforms/database.go | ||
os_str = os_str.lower() | ||
if os_str == 'macos': | ||
os_str = 'darwin' | ||
return os_str | ||
|
||
|
||
_NORMALIZE_ARCH = { | ||
("i386", None): ("386", ""), | ||
("x86_64", "v1"): ("amd64", ""), | ||
("x86-64", "v1"): ("amd64", ""), | ||
("amd64", "v1"): ("amd64", ""), | ||
("x86_64", None): ("amd64", None), | ||
("x86-64", None): ("amd64", None), | ||
("amd64", None): ("amd64", None), | ||
("aarch64", "8"): ("arm64", ""), | ||
("arm64", "8"): ("arm64", ""), | ||
("aarch64", "v8"): ("arm64", ""), | ||
("arm64", "v8"): ("arm64", ""), | ||
("aarch64", None): ("arm64", None), | ||
("arm64", None): ("arm64", None), | ||
("armhf", None): ("arm", "v7"), | ||
("armel", None): ("arm", "v6"), | ||
("arm", ""): ("arm", "v7"), | ||
("arm", "5"): ("arm", "v5"), | ||
("arm", "6"): ("arm", "v6"), | ||
("arm", "7"): ("arm", "v7"), | ||
("arm", "8"): ("arm", "v8"), | ||
("arm", None): ("arm", None), | ||
} | ||
|
||
|
||
def _normalize_arch(arch_str, variant_str): | ||
# See normalizeArch() in https://github.com/containerd/containerd/blob/main/platforms/database.go | ||
arch_str = arch_str.lower() | ||
variant_str = variant_str.lower() | ||
res = _NORMALIZE_ARCH.get((arch_str, variant_str)) | ||
if res is None: | ||
res = _NORMALIZE_ARCH.get((arch_str, None)) | ||
if res is None: | ||
return arch_str, variant_str | ||
if res is not None: | ||
arch_str = res[0] | ||
if res[1] is not None: | ||
variant_str = res[1] | ||
return arch_str, variant_str | ||
|
||
|
||
class _Platform(object): | ||
def __init__(self, os=None, arch=None, variant=None): | ||
self.os = os | ||
self.arch = arch | ||
self.variant = variant | ||
if variant is not None: | ||
if arch is None: | ||
raise ValueError('If variant is given, architecture must be given too') | ||
if os is None: | ||
raise ValueError('If variant is given, os must be given too') | ||
|
||
@classmethod | ||
def parse_platform_string(cls, string, daemon_os=None, daemon_arch=None): | ||
# See Parse() in https://github.com/containerd/containerd/blob/main/platforms/platforms.go | ||
if string is None: | ||
return cls() | ||
if not string: | ||
raise ValueError('Platform string must be non-empty') | ||
parts = string.split('/', 2) | ||
arch = None | ||
variant = None | ||
if len(parts) == 1: | ||
_validate_part(string, string, 'OS/architecture') | ||
# The part is either OS or architecture | ||
os = _normalize_os(string) | ||
if os in _KNOWN_OS: | ||
if daemon_arch is not None: | ||
arch, variant = _normalize_arch(daemon_arch, '') | ||
return cls(os=os, arch=arch, variant=variant) | ||
arch, variant = _normalize_arch(os, '') | ||
if arch in _KNOWN_ARCH: | ||
return cls( | ||
os=_normalize_os(daemon_os) if daemon_os else None, | ||
arch=arch or None, | ||
variant=variant or None, | ||
) | ||
raise ValueError('Invalid platform string "{0}": unknown OS or architecture'.format(string)) | ||
os = _validate_part(string, parts[0], 'OS') | ||
if not os: | ||
raise ValueError('Invalid platform string "{0}": OS is empty'.format(string)) | ||
arch = _validate_part(string, parts[1], 'architecture') if len(parts) > 1 else None | ||
if arch is not None and not arch: | ||
raise ValueError('Invalid platform string "{0}": architecture is empty'.format(string)) | ||
variant = _validate_part(string, parts[2], 'variant') if len(parts) > 2 else None | ||
if variant is not None and not variant: | ||
raise ValueError('Invalid platform string "{0}": variant is empty'.format(string)) | ||
arch, variant = _normalize_arch(arch, variant or '') | ||
if len(parts) == 2 and arch == 'arm' and variant == 'v7': | ||
variant = None | ||
if len(parts) == 3 and arch == 'arm64' and variant == '': | ||
variant = 'v8' | ||
return cls(os=_normalize_os(os), arch=arch, variant=variant or None) | ||
|
||
def __str__(self): | ||
if self.variant: | ||
parts = [self.os, self.arch, self.variant] | ||
elif self.os: | ||
if self.arch: | ||
parts = [self.os, self.arch] | ||
else: | ||
parts = [self.os] | ||
elif self.arch is not None: | ||
parts = [self.arch] | ||
else: | ||
parts = [] | ||
return '/'.join(parts) | ||
|
||
def __repr__(self): | ||
return '_Platform(os={os!r}, arch={arch!r}, variant={variant!r})'.format(os=self.os, arch=self.arch, variant=self.variant) | ||
|
||
def __eq__(self, other): | ||
return self.os == other.os and self.arch == other.arch and self.variant == other.variant | ||
|
||
|
||
def normalize_platform_string(string, daemon_os=None, daemon_arch=None): | ||
return str(_Platform.parse_platform_string(string, daemon_os=daemon_os, daemon_arch=daemon_arch)) | ||
|
||
|
||
def compose_platform_string(os=None, arch=None, variant=None, daemon_os=None, daemon_arch=None): | ||
if os is None and daemon_os is not None: | ||
os = _normalize_os(daemon_os) | ||
if arch is None and daemon_arch is not None: | ||
arch, variant = _normalize_arch(daemon_arch, variant or '') | ||
variant = variant or None | ||
return str(_Platform(os=os, arch=arch, variant=variant or None)) | ||
|
||
|
||
def compare_platform_strings(string1, string2): | ||
return _Platform.parse_platform_string(string1) == _Platform.parse_platform_string(string2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.