Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ceph_orch_apply: Improve by adding idempotency #288

Merged
merged 1 commit into from
May 15, 2024
Merged
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
84 changes: 68 additions & 16 deletions library/ceph_orch_apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
# limitations under the License.

from __future__ import absolute_import, division, print_function
from typing import List, Tuple
from typing import List, Tuple, Dict
__metaclass__ = type

import datetime
import yaml

from ansible.module_utils.basic import AnsibleModule # type: ignore
try:
from ansible.module_utils.ceph_common import exit_module, build_base_cmd_orch # type: ignore
except ImportError:
from module_utils.ceph_common import exit_module, build_base_cmd_orch
import datetime


ANSIBLE_METADATA = {
Expand Down Expand Up @@ -70,6 +72,40 @@
'''


def parse_spec(spec: str) -> Dict:
""" parse spec string to yaml """
yaml_spec = yaml.safe_load(spec)
return yaml_spec


def retrieve_current_spec(module: AnsibleModule, expected_spec: Dict) -> Dict:
""" retrieve current config of the service """
service: str = expected_spec["service_type"]
cmd = build_base_cmd_orch(module)
cmd.extend(['ls', service, '--format=yaml'])
out = module.run_command(cmd)
if isinstance(out, str):
# if there is no existing service, cephadm returns the string 'No services reported'
return {}
else:
return yaml.safe_load(out[1])


def change_required(current: Dict, expected: Dict) -> bool:
""" checks if the current config differs from what is expected """
if not current:
return True

for key, value in expected.items():
if key in current:
if current[key] != value:
return True
continue
else:
return True
return False


def apply_spec(module: "AnsibleModule",
data: str) -> Tuple[int, List[str], str, str]:
cmd = build_base_cmd_orch(module)
Expand All @@ -82,23 +118,24 @@ def apply_spec(module: "AnsibleModule",
return rc, cmd, out, err


def main() -> None:
def run_module() -> None:

module_args = dict(
spec=dict(type='str', required=True),
fsid=dict(type='str', required=False),
docker=dict(type=bool,
required=False,
default=False),
image=dict(type='str', required=False)
)

module = AnsibleModule(
argument_spec=dict(
fsid=dict(type='str', required=False),
spec=dict(type='str', required=True),
docker=dict(type=bool,
required=False,
default=False),
image=dict(type='str', required=False)
),
argument_spec=module_args,
supports_check_mode=True
)

spec = module.params.get('spec')

startd = datetime.datetime.now()
changed = False
spec = module.params.get('spec')

if module.check_mode:
exit_module(
Expand All @@ -111,8 +148,19 @@ def main() -> None:
changed=False
)

rc, cmd, out, err = apply_spec(module, spec)
changed = True
# Idempotency check
expected = parse_spec(module.params.get('spec'))
current_spec = retrieve_current_spec(module, expected)

if change_required(current_spec, expected):
rc, cmd, out, err = apply_spec(module, spec)
changed = True
else:
rc = 0
cmd = []
out = ''
err = ''
changed = False

exit_module(
module=module,
Expand All @@ -125,5 +173,9 @@ def main() -> None:
)


def main() -> None:
run_module()


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ skipsdist = True
basepython = python3
deps =
mypy
types-PyYAML
commands = mypy --config-file ./mypy.ini {toxinidir}/library {toxinidir}/module_utils

[testenv:flake8]
Expand Down
Loading