Control Get Existing Resource With Id#

Idem resource provider plugins that implement “resource” contract look-up existing resource by resource_id. If resource_id is not provided as the “present” and “absent” function arguments, resource can be looked-up by name or any other attribute that uniquely identify resource in the provider.

However, it should be possible to control Idem plugins behaviour to look-up existing resource only if resource_id specified in SLS or stored in ESM cache. Command line argument --get-resource-only-with-resource-id allows to control this behaviour.

idem state ~/instance_test.sls --get-resource-only-with-resource-id

All Idem resource provider plugins “present” and “absent” functions should read “get_resource_only_with_resource_id” property to control look-up existing resource logic.

import copy

__contracts__ = ["resource"]


async def present(hub, ctx, name, resource_id, **kwargs):
    """
    Check if a resource exists, if it doesn't create it.
    If the resource exists, make sure that it is in the state described by "kwargs"
    """
    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    if resource_id:
        before = await hub.exec.cloud.resource.get(
            ctx, name=name, resource_id=resource_id
        )

        if not before["result"] or not before["ret"]:
            result["comment"] = before["comment"]
            result["result"] = False
            return result

        result["old_state"] = copy.deepcopy(before["ret"])

    elif not hub.OPT.idem.get("get_resource_only_with_resource_id", False):
        before = await hub.exec.cloud.resource.get(ctx, name=name, **kwargs)

        if not before["result"]:
            result["comment"] = before["comment"]
            result["result"] = False
            return result

        if before["ret"]:
            result["old_state"] = copy.deepcopy(before["ret"])

    if result["old_state"]:
        # Update resource
        update = await hub.exec.cloud.resource.update(
            ctx, name=name, resource_id=resource_id, **kwargs
        )

        if not update["result"]:
            result["comment"] = update["comment"]
            result["result"] = False
            return result

        result["comment"] = f"Updated cloud.resource '{name}'"
        result["new_state"] = copy.deepcopy(update["ret"])
    else:
        # Create resource
        create = await hub.exec.cloud.resource.create(ctx, name=name, **kwargs)

        if not create["result"]:
            result["comment"] = create["comment"]
            result["result"] = False
            return result

        result["comment"] = f"Created cloud.resource '{name}'"
        result["new_state"] = copy.deepcopy(create["ret"])

    return result


async def absent(hub, ctx, resource_id, name, **kwargs):
    """
    Check if a resource exists, if it exists delete it
    """
    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    before = {}

    if resource_id:
        before = await hub.exec.cloud.resource.get(
            ctx, name=name, resource_id=resource_id
        )

        if not before["result"]:
            result["comment"] = before["comment"]
            result["result"] = False
            return result

        if before["ret"]:
            result["old_state"] = copy.deepcopy(before["ret"])

    elif not hub.OPT.idem.get("get_resource_only_with_resource_id", False):
        before = await hub.exec.cloud.resource.get(ctx, name=name, **kwargs)

        if not before["result"]:
            result["comment"] = before["comment"]
            result["result"] = False
            return result

        if before["ret"]:
            result["old_state"] = copy.deepcopy(before["ret"])

    if result["old_state"]:
        # Delete resource
        delete = await hub.exec.cloud.resource.delete(
            ctx, name=name, resource_id=resource_id, **kwargs
        )

        if not delete["result"]:
            result["comment"] = delete["comment"]
            result["result"] = False
            return result

        result["comment"] = f"Deleted cloud.resource '{name}'"
    else:
        # Resource doesn't exist
        result["comment"] = f"cloud.resource '{name}' already absent"

    return result


def describe(hub, ctx, name):
    ...