mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-26 21:33:02 +00:00
Port changes from main to refactored branch Depends-on: ansible/ansible-zuul-jobs#1563 SUMMARY This PR contains several commits that complete the rebase of the 2.x-refactor branch onto main. Most of the changes here had to be manually backported after rebasing as the original changes were to code that will be deprecated. In addition, rather than trying to manually sort out conflicts and changes to the sanity ignores, I rewrote the refresh_ignore_files script to fully automate the management of ignore files. Previously, these files were both manually edited and auto-generated. This should no longer be the case, and these files should never be manually edited going forward. For the purposes of reviewing and history, I kept all changes in separate commits tied to the original commit being backported. ISSUE TYPE COMPONENT NAME ADDITIONAL INFORMATION Reviewed-by: Jill R <None>
130 lines
4.5 KiB
Python
130 lines
4.5 KiB
Python
# Copyright: (c) 2021, Red Hat | Ansible
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
import os
|
|
from typing import cast, Dict, Iterable, List, Optional, Union
|
|
|
|
from ansible.module_utils.six import string_types
|
|
|
|
try:
|
|
import yaml
|
|
except ImportError:
|
|
# Handled in module setup
|
|
pass
|
|
|
|
|
|
class ResourceDefinition(dict):
|
|
"""Representation of a resource definition.
|
|
|
|
This is a thin wrapper around a dictionary representation of a resource
|
|
definition, with a few properties defined for conveniently accessing the
|
|
commonly used fields.
|
|
"""
|
|
|
|
@property
|
|
def kind(self) -> Optional[str]:
|
|
return self.get("kind")
|
|
|
|
@property
|
|
def api_version(self) -> Optional[str]:
|
|
return self.get("apiVersion")
|
|
|
|
@property
|
|
def namespace(self) -> Optional[str]:
|
|
metadata = self.get("metadata", {})
|
|
return metadata.get("namespace")
|
|
|
|
@property
|
|
def name(self) -> Optional[str]:
|
|
metadata = self.get("metadata", {})
|
|
return metadata.get("name")
|
|
|
|
|
|
def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
|
"""Create a list of ResourceDefinitions from module inputs.
|
|
|
|
This will take the module's inputs and return a list of ResourceDefintion
|
|
objects. The resource definitions returned by this function should be as
|
|
complete a definition as we can create based on the input. Any *List kinds
|
|
will be removed and replaced by the resources contained in it.
|
|
"""
|
|
if params.get("resource_definition"):
|
|
d = cast(Union[str, List, Dict], params.get("resource_definition"))
|
|
definitions = from_yaml(d)
|
|
elif params.get("src"):
|
|
d = cast(str, params.get("src"))
|
|
definitions = from_file(d)
|
|
else:
|
|
# We'll create an empty definition and let merge_params set values
|
|
# from the module parameters.
|
|
definitions = [{}]
|
|
|
|
resource_definitions: List[Dict] = []
|
|
for definition in definitions:
|
|
merge_params(definition, params)
|
|
kind = cast(Optional[str], definition.get("kind"))
|
|
if kind and kind.endswith("List"):
|
|
resource_definitions += flatten_list_kind(definition, params)
|
|
else:
|
|
resource_definitions.append(definition)
|
|
return list(map(ResourceDefinition, resource_definitions))
|
|
|
|
|
|
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
|
"""Load resource definitions from a yaml definition."""
|
|
definitions: List[Dict] = []
|
|
if isinstance(definition, string_types):
|
|
definitions += yaml.safe_load_all(definition)
|
|
elif isinstance(definition, list):
|
|
for item in definition:
|
|
if isinstance(item, string_types):
|
|
definitions += yaml.safe_load_all(item)
|
|
else:
|
|
definitions.append(item)
|
|
else:
|
|
definition = cast(Dict, definition)
|
|
definitions.append(definition)
|
|
return filter(None, definitions)
|
|
|
|
|
|
def from_file(filepath: str) -> Iterable[Dict]:
|
|
"""Load resource definitions from a path to a yaml file."""
|
|
path = os.path.normpath(filepath)
|
|
with open(path, "rb") as f:
|
|
definitions = list(yaml.safe_load_all(f))
|
|
return filter(None, definitions)
|
|
|
|
|
|
def merge_params(definition: Dict, params: Dict) -> Dict:
|
|
"""Merge module parameters with the resource definition.
|
|
|
|
Fields in the resource definition take precedence over module parameters.
|
|
"""
|
|
definition.setdefault("kind", params.get("kind"))
|
|
definition.setdefault("apiVersion", params.get("api_version"))
|
|
metadata = definition.setdefault("metadata", {})
|
|
# The following should only be set if we have values for them
|
|
if params.get("namespace"):
|
|
metadata.setdefault("namespace", params.get("namespace"))
|
|
if params.get("name"):
|
|
metadata.setdefault("name", params.get("name"))
|
|
if params.get("generate_name"):
|
|
metadata.setdefault("generateName", params.get("generate_name"))
|
|
return definition
|
|
|
|
|
|
def flatten_list_kind(definition: Dict, params: Dict) -> List[Dict]:
|
|
"""Replace *List kind with the items it contains.
|
|
|
|
This will take a definition for a *List resource and return a list of
|
|
definitions for the items contained within the List.
|
|
"""
|
|
items = []
|
|
kind = cast(str, definition.get("kind"))[:-4]
|
|
api_version = definition.get("apiVersion")
|
|
for item in definition.get("items", []):
|
|
item.setdefault("kind", kind)
|
|
item.setdefault("apiVersion", api_version)
|
|
items.append(merge_params(item, params))
|
|
return items
|