|
|
|
|
@ -16,8 +16,6 @@ except ImportError:
|
|
|
|
|
_query_params_to_string,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
DOCUMENTATION = r"""
|
|
|
|
|
---
|
|
|
|
|
module: portainer_stack
|
|
|
|
|
@ -119,15 +117,17 @@ def _create_stack(client, module, file_contents):
|
|
|
|
|
|
|
|
|
|
def _update_stack(client, module, stack_id):
|
|
|
|
|
target_stack_name = module.params["stack_name"]
|
|
|
|
|
contents = _get_stack_contents(module.params)
|
|
|
|
|
with open(module.params["docker_compose_file_path"]) as f:
|
|
|
|
|
file_contents = f.read()
|
|
|
|
|
return client.put(
|
|
|
|
|
f"stacks/{stack_id}?&endpointId={client.endpoint}",
|
|
|
|
|
body={
|
|
|
|
|
"name": target_stack_name,
|
|
|
|
|
"stackFileContent": contents,
|
|
|
|
|
"stackFileContent": file_contents,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def handle_state_present(client, module):
|
|
|
|
|
result = dict(changed=False, stack_name=module.params["stack_name"])
|
|
|
|
|
|
|
|
|
|
@ -135,7 +135,8 @@ def handle_state_present(client, module):
|
|
|
|
|
stacks = client.get("stacks")
|
|
|
|
|
result["stacks"] = stacks
|
|
|
|
|
|
|
|
|
|
contents = _get_stack_contents(module.params)
|
|
|
|
|
with open(module.params["docker_compose_file_path"]) as f:
|
|
|
|
|
file_contents = f.read()
|
|
|
|
|
|
|
|
|
|
target_stack_name = module.params["stack_name"]
|
|
|
|
|
for stack in stacks:
|
|
|
|
|
@ -145,7 +146,7 @@ def handle_state_present(client, module):
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if not already_exists:
|
|
|
|
|
stack = _create_stack(client, module, contents)
|
|
|
|
|
stack = _create_stack(client, module, file_contents)
|
|
|
|
|
result["changed"] = True
|
|
|
|
|
result["stack_id"] = stack["Id"]
|
|
|
|
|
module.exit_json(**result)
|
|
|
|
|
@ -157,7 +158,7 @@ def handle_state_present(client, module):
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
result["are_equal"] = (
|
|
|
|
|
current_file_contents_resp["StackFileContent"] == contents
|
|
|
|
|
current_file_contents_resp["StackFileContent"] == file_contents
|
|
|
|
|
)
|
|
|
|
|
if result["are_equal"]:
|
|
|
|
|
module.exit_json(**result)
|
|
|
|
|
@ -190,22 +191,13 @@ def handle_state_absent(client, module):
|
|
|
|
|
)
|
|
|
|
|
result["changed"] = True
|
|
|
|
|
module.exit_json(**result)
|
|
|
|
|
def _get_stack_contents(params):
|
|
|
|
|
if params.get("docker_compose_file_path"):
|
|
|
|
|
with open(params["docker_compose_file_path"]) as f:
|
|
|
|
|
return f.read()
|
|
|
|
|
|
|
|
|
|
if params.get("definition"):
|
|
|
|
|
return yaml.dump(params["definition"], indent=2)
|
|
|
|
|
|
|
|
|
|
raise ValueError("No docker_compose_file_path or definition provided.")
|
|
|
|
|
|
|
|
|
|
def run_module():
|
|
|
|
|
# define available arguments/parameters a user can pass to the module
|
|
|
|
|
module_args = dict(
|
|
|
|
|
stack_name=dict(type="str", required=True),
|
|
|
|
|
docker_compose_file_path=dict(type="str"),
|
|
|
|
|
definition=dict(type=dict),
|
|
|
|
|
username=dict(type="str", default="admin"),
|
|
|
|
|
password=dict(type="str", required=True, no_log=True),
|
|
|
|
|
endpoint_id=dict(type="int", required=True),
|
|
|
|
|
@ -213,6 +205,11 @@ def run_module():
|
|
|
|
|
state=dict(type="str", default="present", choices=["present", "absent"]),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
required_if = [
|
|
|
|
|
# docker compose file is only required if we are ensuring the stack is present.
|
|
|
|
|
["state", "present", ("docker_compose_file_path",)],
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
state_fns = {"present": handle_state_present, "absent": handle_state_absent}
|
|
|
|
|
|
|
|
|
|
# the AnsibleModule object will be our abstraction working with Ansible
|
|
|
|
|
@ -221,16 +218,7 @@ def run_module():
|
|
|
|
|
# supports check mode
|
|
|
|
|
module = AnsibleModule(
|
|
|
|
|
argument_spec=module_args,
|
|
|
|
|
# required_if = [
|
|
|
|
|
# docker compose file is only required if we are ensuring the stack is present.
|
|
|
|
|
# ["state", "present", ("docker_compose_file_path",)],
|
|
|
|
|
# ],
|
|
|
|
|
mutually_exclusive=[
|
|
|
|
|
('docker_compose_file_path', 'definition'),
|
|
|
|
|
],
|
|
|
|
|
required_one_of=[
|
|
|
|
|
('docker_compose_file_path', 'definition'),
|
|
|
|
|
],
|
|
|
|
|
required_if=required_if,
|
|
|
|
|
# TODO: support check mode
|
|
|
|
|
supports_check_mode=False,
|
|
|
|
|
)
|
|
|
|
|
|