Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelogs/fragments/202030630-amazon_cloud_fixes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bugfixes:
- "amazon.cloud - Add the original option name as an alias to avoid issues when snake cased option names are not correctly reversed to CamelCase."
- "amazon.cloud - Update cleanup documentation function."
- "amazon.cloud - Add some temporary workarounds for 'AWS::RDS::DBInstance' resource."
- "amazon.cloud - Use module_openapi_cloud__examples rather than examples in generate_cloud_example.py"
15 changes: 10 additions & 5 deletions plugins/action/generate_cloud_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ def inject(


class ActionModule(ActionBase):

def __init__(self, *args, **kwargs):
super(ActionModule, self).__init__(*args, **kwargs)
self._validator_name = None
Expand Down Expand Up @@ -270,13 +269,15 @@ def run(self, tmp=None, task_vars=None):

galaxy_file = args.get("target_dir") + "/galaxy.yml"
galaxy = yaml.safe_load(Path(galaxy_file).open())
vars_file = task_vars['vars']['role_path'] + "/vars/main.yaml"
vars_file = task_vars["vars"]["role_path"] + "/vars/main.yaml"
vars = yaml.safe_load(Path(vars_file).open())
collection_name = f"{galaxy['namespace']}.{galaxy['name']}"
tasks = []
test_scenarios_dirs = [
Path(args.get("target_dir")) / Path(i)
for i in vars["examples"][collection_name]["load_from"]
for i in vars["module_openapi_cloud__examples"][collection_name][
"load_from"
]
]
for scenario_dir in test_scenarios_dirs:
if not scenario_dir.is_dir():
Expand All @@ -289,8 +290,12 @@ def run(self, tmp=None, task_vars=None):
extracted_examples = extract(
tasks,
collection_name,
dont_look_up_vars=vars["examples"][collection_name]["dont_look_up_vars"],
task_selector=vars["examples"][collection_name]["task_selector"],
dont_look_up_vars=vars["module_openapi_cloud__examples"][collection_name][
"dont_look_up_vars"
],
task_selector=vars["module_openapi_cloud__examples"][collection_name][
"task_selector"
],
)
inject(Path(args.get("target_dir")), extracted_examples)
return self._result
86 changes: 57 additions & 29 deletions plugins/action/generate_cloud_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import copy
from typing import Dict, Iterable, List, DefaultDict, Union, Optional, TypeVar, Type
from ansible.plugins.action import ActionBase
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils.content_library_data import content_library_static_ds
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils.content_library_data import (
content_library_static_ds,
)
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils.utils import (
format_documentation,
indent,
Expand All @@ -34,8 +36,11 @@
camel_to_snake,
ignore_description,
)

# import for amazon.cloud doc generation
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils.generator import generate_documentation
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils.generator import (
generate_documentation,
)


# vmware specific
Expand Down Expand Up @@ -202,7 +207,6 @@ def gen_documentation(
next_version: str,
target_dir: str,
) -> Dict:

short_description = description.split(". ")[0]
documentation = {
"author": ["Ansible Cloud Team (@ansible-collections)"],
Expand Down Expand Up @@ -466,23 +470,32 @@ def gen_mutually_exclusive(schema: Dict) -> List:
primary_idenfifier = schema.get("primaryIdentifier", [])
entries: List = []

if len(primary_idenfifier) > 1:
entries.append([tuple(primary_idenfifier), "identifier"])
_primary_idenfifier = [
camel_to_snake(id.split("/")[-1], alias=False) for id in primary_idenfifier
]

if len(_primary_idenfifier) > 1:
entries.append([tuple(_primary_idenfifier), "identifier"])

return entries


def ensure_all_identifiers_defined(schema: Dict) -> str:
primary_idenfifier = schema.get("primaryIdentifier", [])
_primary_idenfifier = [item.split("/")[-1] for item in primary_idenfifier]
new_content: str = "if state in ('present', 'absent', 'get', 'describe') and module.params.get('identifier') is None:\n"
new_content += 8 * " "
new_content += f"if not module.params.get('{primary_idenfifier[0]}')" + " ".join(
map(lambda x: f" or not module.params.get('{x}')", primary_idenfifier[1:])
)
new_content += ":\n" + 12 * " "
new_content += (
"module.fail_json(f'You must specify both {*identifier, } identifiers.')\n"
f"if not module.params.get('{camel_to_snake(_primary_idenfifier[0])}')"
+ " ".join(
map(
lambda x: f" or not module.params.get('{camel_to_snake(x)}')",
_primary_idenfifier[1:],
)
)
)
new_content += ":\n" + 12 * " "
new_content += f'module.fail_json("You must specify all the {*[camel_to_snake(id) for id in _primary_idenfifier], } identifiers.")\n'

return new_content

Expand Down Expand Up @@ -511,19 +524,28 @@ def gen_required_if(schema: Union[List, Dict]) -> List:
entries: List = []
states = ["absent", "get"]

_primary_idenfifier = copy.copy(primary_idenfifier)
_primary_idenfifier = [
camel_to_snake(id.split("/")[-1], alias=False) for id in primary_idenfifier
]

# For compound primary identifiers consisting of multiple resource properties strung together,
# use the property values in the order that they are specified in the primary identifier definition
if len(primary_idenfifier) > 1:
entries.append(["state", "list", primary_idenfifier[:-1], True])
if len(_primary_idenfifier) > 1:
entries.append(["state", "list", _primary_idenfifier[:-1], True])
_primary_idenfifier.append("identifier")

entries.append(
[
"state",
"present",
list(set([*_primary_idenfifier, *required])),
list(
set(
[
*_primary_idenfifier,
*[camel_to_snake(id, alias=False) for id in required],
]
)
),
True,
]
)
Expand Down Expand Up @@ -559,8 +581,12 @@ def generate_module_name(self) -> str:
list_to_str = "".join(map(str, splitted[2:]))
return prefix + "_" + camel_to_snake(list_to_str)

def renderer(self, target_dir: str, module_dir: str, next_version: str, role_path: str):
added_ins = get_module_added_ins(self.name, git_dir=pathlib.Path(target_dir + "/.git"))
def renderer(
self, target_dir: str, module_dir: str, next_version: str, role_path: str
):
added_ins = get_module_added_ins(
self.name, git_dir=pathlib.Path(target_dir + "/.git")
)
documentation = generate_documentation(
self,
added_ins,
Expand All @@ -570,7 +596,6 @@ def renderer(self, target_dir: str, module_dir: str, next_version: str, role_pat

arguments = generate_argument_spec(documentation["options"])
documentation_to_string = format_documentation(documentation)

content = jinja2_renderer(
self.template_file,
role_path,
Expand Down Expand Up @@ -763,7 +788,6 @@ def sort_operationsid(input: Iterable) -> Iterable:
len(set(self.default_operationIds) - set(result["operationIds"]))
> 0
):

required_with = []
for i in result["operationIds"]:
state = ansible_state(i, self.default_operationIds)
Expand Down Expand Up @@ -935,8 +959,9 @@ def list_path(self) -> any:

return list_path

def renderer(self, target_dir: str, module_dir: str, next_version: str, role_path: str):

def renderer(
self, target_dir: str, module_dir: str, next_version: str, role_path: str
):
added_ins = {} # get_module_added_ins(self.name, git_dir=target_dir / ".git")
arguments = gen_arguments_py(self.parameters(), self.list_index())
documentation = format_documentation(
Expand Down Expand Up @@ -1231,7 +1256,7 @@ def generate_amazon_cloud(args: Iterable, role_path: str):
meta_dir = pathlib.Path(args.get("target_dir") + "/meta")
meta_dir.mkdir(parents=True, exist_ok=True)
yaml_dict = {
"requires_ansible": """>=2.11.0""",
"requires_ansible": """>=2.13.0""",
"action_groups": {"aws": []},
"plugin_routing": {"modules": {}},
}
Expand Down Expand Up @@ -1291,7 +1316,7 @@ def generate_vmware_rest(args: Iterable, role_path: str):
target_dir=args.get("target_dir"),
module_dir=args.get("modules"),
next_version=args.get("next_version"),
role_path=role_path
role_path=role_path,
)
module_list.append(module.name)
elif "get" in resource.operations:
Expand All @@ -1314,19 +1339,21 @@ def generate_vmware_rest(args: Iterable, role_path: str):
resource, definitions=swagger_file.definitions
)

if module.is_trusted(args.get("modules")) and len(module.default_operationIds) > 0:
if (
module.is_trusted(args.get("modules"))
and len(module.default_operationIds) > 0
):
module.renderer(
target_dir=args.get("target_dir"),
module_dir=args.get("modules"),
next_version=args.get("next_version"),
role_path=role_path
role_path=role_path,
)
module_list.append(module.name)
return


class ActionModule(ActionBase):

def __init__(self, *args, **kwargs):
super(ActionModule, self).__init__(*args, **kwargs)
self._validator_name = None
Expand All @@ -1349,12 +1376,14 @@ def run(self, tmp=None, task_vars=None):
:return: The results from the parser
:rtype: dict
"""

self._result = super(ActionModule, self).run(tmp, task_vars)
self._task_vars = task_vars

args = self._task.args
func = "generate_" + args['collection'] + "(args, task_vars['vars']['role_path'])"
func = (
"generate_" + args["collection"] + "(args, task_vars['vars']['role_path'])"
)
eval(func)

# info = VersionInfo("content_builder")
Expand All @@ -1364,7 +1393,6 @@ def run(self, tmp=None, task_vars=None):
"The modules are autogenerated by:\n"
"https://github.com/ansible-community/ansible.content_builder\n"
""

)
)
dev_md = pathlib.Path(args.get("target_dir") + "/commit_message")
Expand Down
31 changes: 10 additions & 21 deletions plugins/action/generate_cloud_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@
import yaml
from ansible_collections.ansible.content_builder.plugins.plugin_utils.cloud_utils import (
generator,
utils
utils,
)
from ansible.plugins.action import ActionBase



class Schema(TypedDict):
"""A type for the JSONSchema spec"""

Expand All @@ -34,26 +33,10 @@ class Schema(TypedDict):
def generate_schema(raw_content) -> Dict:
json_content = json.loads(raw_content)
schema: Dict[str, Schema] = json_content

for key, value in schema.items():
if key not in ("anyOf", "oneOf"):
if isinstance(value, list):
elems = []
for v in value:
if isinstance(v, list):
elems.extend(
[utils.camel_to_snake(p.split("/")[-1].strip()) for p in v]
)
else:
elems.append(utils.camel_to_snake(v.split("/")[-1].strip()))

schema[key] = elems

return schema


class ActionModule(ActionBase):

def __init__(self, *args, **kwargs):
super(ActionModule, self).__init__(*args, **kwargs)
self._validator_name = None
Expand Down Expand Up @@ -92,12 +75,18 @@ def run(self, tmp=None, task_vars=None):
type_name = v["resource"]
print("Collecting Schema")
print(type_name)
cloudformation = generator.CloudFormationWrapper(boto3.client("cloudformation"))
cloudformation = generator.CloudFormationWrapper(
boto3.client("cloudformation")
)
raw_content = cloudformation.generate_docs(type_name)
schema = generate_schema(raw_content)
file_name = re.sub("::", "_", type_name)
if not pathlib.Path(args.get("api_object_path")).exists():
pathlib.Path(args.get("api_object_path")).mkdir(parents=True, exist_ok=True)
schema_file = pathlib.Path(args.get("api_object_path") + "/" + file_name + ".json")
pathlib.Path(args.get("api_object_path")).mkdir(
parents=True, exist_ok=True
)
schema_file = pathlib.Path(
args.get("api_object_path") + "/" + file_name + ".json"
)
schema_file.write_text(json.dumps(schema, indent=2))
return self._result
Loading