Ensure a given cache cluster exists.

    name
        Name of the cache cluster (cache cluster id).

    wait
        Integer describing how long, in seconds, to wait for confirmation from AWS that the
        resource is in the desired state.  Zero meaning to return success or failure immediately
        of course.  Note that waiting for the cluster to become available is generally the
        better course, as failure to do so will often lead to subsequent failures when managing
        dependent resources.

    security_groups
        One or more VPC security groups (names and/or IDs) associated with the cache cluster.

        .. note::
            This is additive with any sec groups provided via the
            SecurityGroupIds parameter below.  Use this parameter ONLY when you
            are creating a cluster in a VPC.

    CacheClusterId
        The node group (shard) identifier. This parameter is stored as a lowercase string.

        Constraints:

        - A name must contain from 1 to 20 alphanumeric characters or hyphens.
        - The first character must be a letter.
        - A name cannot end with a hyphen or contain two consecutive hyphens.

        .. note::
            In general this parameter is not needed, as 'name' is used if it's
            not provided.

    ReplicationGroupId
        The ID of the replication group to which this cache cluster should belong. If this
        parameter is specified, the cache cluster is added to the specified replication
        group as a read replica; otherwise, the cache cluster is a standalone primary that
        is not part of any replication group.  If the specified replication group is
        Multi-AZ enabled and the Availability Zone is not specified, the cache cluster is
        created in Availability Zones that provide the best spread of read replicas across
        Availability Zones.

        .. note:
            This parameter is ONLY valid if the Engine parameter is redis. Due
            to current limitations on Redis (cluster mode disabled), this
            parameter is not supported on Redis (cluster mode enabled)
            replication groups.

    AZMode
        Specifies whether the nodes in this Memcached cluster are created in a single
        Availability Zone or created across multiple Availability Zones in the cluster's
        region. If the AZMode and PreferredAvailabilityZones are not specified,
        ElastiCache assumes single-az mode.

        .. note::
            This parameter is ONLY supported for Memcached cache clusters.

    PreferredAvailabilityZone
        The EC2 Availability Zone in which the cache cluster is created.  All nodes
        belonging to this Memcached cache cluster are placed in the preferred Availability
        Zone. If you want to create your nodes across multiple Availability Zones, use
        PreferredAvailabilityZones.

        Default:  System chosen Availability Zone.

    PreferredAvailabilityZones
        A list of the Availability Zones in which cache nodes are created. The order of
        the zones in the list is not important.  The number of Availability Zones listed
        must equal the value of NumCacheNodes.  If you want all the nodes in the same
        Availability Zone, use PreferredAvailabilityZone instead, or repeat the
        Availability Zone multiple times in the list.

        Default:  System chosen Availability Zones.

        .. note::
            This option is ONLY supported on Memcached.

            If you are creating your cache cluster in an Amazon VPC
            (recommended) you can only locate nodes in Availability Zones that
            are associated with the subnets in the selected subnet group.

    NumCacheNodes
        The initial (integer) number of cache nodes that the cache cluster has.

        .. note::
            For clusters running Redis, this value must be 1.

            For clusters running Memcached, this value must be between 1 and 20.

    CacheNodeType
        The compute and memory capacity of the nodes in the node group (shard).
        Valid node types (and pricing for them) are exhaustively described at
        https://aws.amazon.com/elasticache/pricing/

        .. note::
            All T2 instances must be created in a VPC

           Redis backup/restore is not supported for Redis (cluster mode
           disabled) T1 and T2 instances. Backup/restore is supported on Redis
           (cluster mode enabled) T2 instances.

           Redis Append-only files (AOF) functionality is not supported for T1
           or T2 instances.

    Engine
        The name of the cache engine to be used for this cache cluster.  Valid values for
        this parameter are:  memcached | redis

    EngineVersion
        The version number of the cache engine to be used for this cache cluster. To view
        the supported cache engine versions, use the DescribeCacheEngineVersions operation.

        .. note::
            You can upgrade to a newer engine version but you cannot downgrade
            to an earlier engine version. If you want to use an earlier engine
            version, you must delete the existing cache cluster or replication
            group and create it anew with the earlier engine version.

    CacheParameterGroupName
        The name of the parameter group to associate with this cache cluster. If this
        argument is omitted, the default parameter group for the specified engine is used.
        You cannot use any parameter group which has cluster-enabled='yes' when creating
        a cluster.

    CacheSubnetGroupName
        The name of the Cache Subnet Group to be used for the cache cluster.  Use this
        parameter ONLY when you are creating a cache cluster within a VPC.

        .. note::
            If you're going to launch your cluster in an Amazon VPC, you need
            to create a subnet group before you start creating a cluster.

    CacheSecurityGroupNames
        A list of Cache Security Group names to associate with this cache cluster.  Use
        this parameter ONLY when you are creating a cache cluster outside of a VPC.

    SecurityGroupIds
        One or more VPC security groups associated with the cache cluster.  Use this
        parameter ONLY when you are creating a cache cluster within a VPC.

    Tags
        A list of tags to be added to this resource.  Note that due to shortcomings in the
        AWS API for Elasticache, these can only be set during resource creation - later
        modification is not (currently) supported.

    SnapshotArns
        A single-element string list containing an Amazon Resource Name (ARN) that
        uniquely identifies a Redis RDB snapshot file stored in Amazon S3. The snapshot
        file is used to populate the node group (shard). The Amazon S3 object name in
        the ARN cannot contain any commas.

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    SnapshotName
        The name of a Redis snapshot from which to restore data into the new node group
        (shard). The snapshot status changes to restoring while the new node group (shard)
        is being created.

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    PreferredMaintenanceWindow
        Specifies the weekly time range during which maintenance on the cache cluster is
        permitted.  It is specified as a range in the format ddd:hh24:mi-ddd:hh24:mi
        (24H Clock UTC).  The minimum maintenance window is a 60 minute period.
        Valid values for ddd are:  sun, mon, tue, wed, thu, fri, sat

        Example:  sun:23:00-mon:01:30

    Port
        The port number on which each of the cache nodes accepts connections.

        Default:  6379

    NotificationTopicArn
        The Amazon Resource Name (ARN) of the Amazon Simple Notification Service (SNS)
        topic to which notifications are sent.

        .. note::
            The Amazon SNS topic owner must be the same as the cache cluster
            owner.

    AutoMinorVersionUpgrade
        This (boolean) parameter is currently disabled.

    SnapshotRetentionLimit
        The number of days for which ElastiCache retains automatic snapshots before
        deleting them.

        Default:  0 (i.e., automatic backups are disabled for this cache cluster).

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    SnapshotWindow
        The daily time range (in UTC) during which ElastiCache begins taking a daily
        snapshot of your node group (shard).  If you do not specify this parameter,
        ElastiCache automatically chooses an appropriate time range.

        Example:  05:00-09:00

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    AuthToken
        The password used to access a password protected server.

        Password constraints:

        - Must be only printable ASCII characters.
        - Must be at least 16 characters and no more than 128 characters in length.
        - Cannot contain any of the following characters: '/', '"', or "@".

    CacheNodeIdsToRemove
        A list of cache node IDs to be removed. A node ID is a numeric identifier (0001, 0002,
        etc.).  This parameter is only valid when NumCacheNodes is less than the existing number of
        cache nodes.  The number of cache node IDs supplied in this parameter must match the
        difference between the existing number of cache nodes in the cluster or pending cache nodes,
        whichever is greater, and the value of NumCacheNodes in the request.

    NewAvailabilityZones
        The list of Availability Zones where the new Memcached cache nodes are created.
        This parameter is only valid when NumCacheNodes in the request is greater than the sum of
        the number of active cache nodes and the number of cache nodes pending creation (which may
        be zero).  The number of Availability Zones supplied in this list must match the cache nodes
        being added in this request.
        Note:  This option is only supported on Memcached clusters.

    NotificationTopicStatus
        The status of the SNS notification topic.  Notifications are sent only if the status is active.

        Valid values:  active | inactive

    region
        Region to connect to.

    key
        Secret key to be used.

    keyid
        Access key to be used.

    profile
        A dict with region, key and keyid, or a pillar key (string) that
        contains a dict with region, key and keyid.

def cache_cluster_present(name, wait=900, security_groups=None, region=None, key=None,
                          keyid=None, profile=None, **args):
    '''
    Ensure a given cache cluster exists.

    name
        Name of the cache cluster (cache cluster id).

    wait
        Integer describing how long, in seconds, to wait for confirmation from AWS that the
        resource is in the desired state.  Zero meaning to return success or failure immediately
        of course.  Note that waiting for the cluster to become available is generally the
        better course, as failure to do so will often lead to subsequent failures when managing
        dependent resources.

    security_groups
        One or more VPC security groups (names and/or IDs) associated with the cache cluster.

        .. note::
            This is additive with any sec groups provided via the
            SecurityGroupIds parameter below.  Use this parameter ONLY when you
            are creating a cluster in a VPC.

    CacheClusterId
        The node group (shard) identifier. This parameter is stored as a lowercase string.

        Constraints:

        - A name must contain from 1 to 20 alphanumeric characters or hyphens.
        - The first character must be a letter.
        - A name cannot end with a hyphen or contain two consecutive hyphens.

        .. note::
            In general this parameter is not needed, as 'name' is used if it's
            not provided.

    ReplicationGroupId
        The ID of the replication group to which this cache cluster should belong. If this
        parameter is specified, the cache cluster is added to the specified replication
        group as a read replica; otherwise, the cache cluster is a standalone primary that
        is not part of any replication group.  If the specified replication group is
        Multi-AZ enabled and the Availability Zone is not specified, the cache cluster is
        created in Availability Zones that provide the best spread of read replicas across
        Availability Zones.

        .. note:
            This parameter is ONLY valid if the Engine parameter is redis. Due
            to current limitations on Redis (cluster mode disabled), this
            parameter is not supported on Redis (cluster mode enabled)
            replication groups.

    AZMode
        Specifies whether the nodes in this Memcached cluster are created in a single
        Availability Zone or created across multiple Availability Zones in the cluster's
        region. If the AZMode and PreferredAvailabilityZones are not specified,
        ElastiCache assumes single-az mode.

        .. note::
            This parameter is ONLY supported for Memcached cache clusters.

    PreferredAvailabilityZone
        The EC2 Availability Zone in which the cache cluster is created.  All nodes
        belonging to this Memcached cache cluster are placed in the preferred Availability
        Zone. If you want to create your nodes across multiple Availability Zones, use
        PreferredAvailabilityZones.

        Default:  System chosen Availability Zone.

    PreferredAvailabilityZones
        A list of the Availability Zones in which cache nodes are created. The order of
        the zones in the list is not important.  The number of Availability Zones listed
        must equal the value of NumCacheNodes.  If you want all the nodes in the same
        Availability Zone, use PreferredAvailabilityZone instead, or repeat the
        Availability Zone multiple times in the list.

        Default:  System chosen Availability Zones.

        .. note::
            This option is ONLY supported on Memcached.

            If you are creating your cache cluster in an Amazon VPC
            (recommended) you can only locate nodes in Availability Zones that
            are associated with the subnets in the selected subnet group.

    NumCacheNodes
        The initial (integer) number of cache nodes that the cache cluster has.

        .. note::
            For clusters running Redis, this value must be 1.

            For clusters running Memcached, this value must be between 1 and 20.

    CacheNodeType
        The compute and memory capacity of the nodes in the node group (shard).
        Valid node types (and pricing for them) are exhaustively described at
        https://aws.amazon.com/elasticache/pricing/

        .. note::
            All T2 instances must be created in a VPC

           Redis backup/restore is not supported for Redis (cluster mode
           disabled) T1 and T2 instances. Backup/restore is supported on Redis
           (cluster mode enabled) T2 instances.

           Redis Append-only files (AOF) functionality is not supported for T1
           or T2 instances.

    Engine
        The name of the cache engine to be used for this cache cluster.  Valid values for
        this parameter are:  memcached | redis

    EngineVersion
        The version number of the cache engine to be used for this cache cluster. To view
        the supported cache engine versions, use the DescribeCacheEngineVersions operation.

        .. note::
            You can upgrade to a newer engine version but you cannot downgrade
            to an earlier engine version. If you want to use an earlier engine
            version, you must delete the existing cache cluster or replication
            group and create it anew with the earlier engine version.

    CacheParameterGroupName
        The name of the parameter group to associate with this cache cluster. If this
        argument is omitted, the default parameter group for the specified engine is used.
        You cannot use any parameter group which has cluster-enabled='yes' when creating
        a cluster.

    CacheSubnetGroupName
        The name of the Cache Subnet Group to be used for the cache cluster.  Use this
        parameter ONLY when you are creating a cache cluster within a VPC.

        .. note::
            If you're going to launch your cluster in an Amazon VPC, you need
            to create a subnet group before you start creating a cluster.

    CacheSecurityGroupNames
        A list of Cache Security Group names to associate with this cache cluster.  Use
        this parameter ONLY when you are creating a cache cluster outside of a VPC.

    SecurityGroupIds
        One or more VPC security groups associated with the cache cluster.  Use this
        parameter ONLY when you are creating a cache cluster within a VPC.

    Tags
        A list of tags to be added to this resource.  Note that due to shortcomings in the
        AWS API for Elasticache, these can only be set during resource creation - later
        modification is not (currently) supported.

    SnapshotArns
        A single-element string list containing an Amazon Resource Name (ARN) that
        uniquely identifies a Redis RDB snapshot file stored in Amazon S3. The snapshot
        file is used to populate the node group (shard). The Amazon S3 object name in
        the ARN cannot contain any commas.

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    SnapshotName
        The name of a Redis snapshot from which to restore data into the new node group
        (shard). The snapshot status changes to restoring while the new node group (shard)
        is being created.

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    PreferredMaintenanceWindow
        Specifies the weekly time range during which maintenance on the cache cluster is
        permitted.  It is specified as a range in the format ddd:hh24:mi-ddd:hh24:mi
        (24H Clock UTC).  The minimum maintenance window is a 60 minute period.
        Valid values for ddd are:  sun, mon, tue, wed, thu, fri, sat

        Example:  sun:23:00-mon:01:30

    Port
        The port number on which each of the cache nodes accepts connections.

        Default:  6379

    NotificationTopicArn
        The Amazon Resource Name (ARN) of the Amazon Simple Notification Service (SNS)
        topic to which notifications are sent.

        .. note::
            The Amazon SNS topic owner must be the same as the cache cluster
            owner.

    AutoMinorVersionUpgrade
        This (boolean) parameter is currently disabled.

    SnapshotRetentionLimit
        The number of days for which ElastiCache retains automatic snapshots before
        deleting them.

        Default:  0 (i.e., automatic backups are disabled for this cache cluster).

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    SnapshotWindow
        The daily time range (in UTC) during which ElastiCache begins taking a daily
        snapshot of your node group (shard).  If you do not specify this parameter,
        ElastiCache automatically chooses an appropriate time range.

        Example:  05:00-09:00

        .. note::
            This parameter is ONLY valid if the Engine parameter is redis.

    AuthToken
        The password used to access a password protected server.

        Password constraints:

        - Must be only printable ASCII characters.
        - Must be at least 16 characters and no more than 128 characters in length.
        - Cannot contain any of the following characters: '/', '"', or "@".

    CacheNodeIdsToRemove
        A list of cache node IDs to be removed. A node ID is a numeric identifier (0001, 0002,
        etc.).  This parameter is only valid when NumCacheNodes is less than the existing number of
        cache nodes.  The number of cache node IDs supplied in this parameter must match the
        difference between the existing number of cache nodes in the cluster or pending cache nodes,
        whichever is greater, and the value of NumCacheNodes in the request.

    NewAvailabilityZones
        The list of Availability Zones where the new Memcached cache nodes are created.
        This parameter is only valid when NumCacheNodes in the request is greater than the sum of
        the number of active cache nodes and the number of cache nodes pending creation (which may
        be zero).  The number of Availability Zones supplied in this list must match the cache nodes
        being added in this request.
        Note:  This option is only supported on Memcached clusters.

    NotificationTopicStatus
        The status of the SNS notification topic.  Notifications are sent only if the status is active.

        Valid values:  active | inactive

    region
        Region to connect to.

    key
        Secret key to be used.

    keyid
        Access key to be used.

    profile
        A dict with region, key and keyid, or a pillar key (string) that
        contains a dict with region, key and keyid.
    '''
    ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
    args = dict([(k, v) for k, v in args.items() if not k.startswith('_')])
    current = __salt__['boto3_elasticache.'
                       'describe_cache_clusters'](name, region=region, key=key,
                                                  keyid=keyid, profile=profile)
    if current:
        check_update = True
    else:
        check_update = False
        only_on_modify = [
            'CacheNodeIdsToRemove',
            'NewAvailabilityZones',
            'NotificationTopicStatus'
        ]
        create_args = {}
        for k, v in args.items():
            if k in only_on_modify:
                check_update = True
            else:
                create_args[k] = v
        if __opts__['test']:
            ret['comment'] = 'Cache cluster {0} would be created.'.format(name)
            ret['result'] = None
            return ret
        created = __salt__['boto3_elasticache.'
                           'create_cache_cluster'](name, wait=wait, security_groups=security_groups,
                                                   region=region, key=key, keyid=keyid,
                                                   profile=profile, **create_args)
        if created:
            new = __salt__['boto3_elasticache.'
                           'describe_cache_clusters'](name, region=region, key=key,
                                                      keyid=keyid, profile=profile)
            ret['comment'] = 'Cache cluster {0} was created.'.format(name)
            ret['changes']['old'] = None
            ret['changes']['new'] = new[0]
        else:
            ret['result'] = False
            ret['comment'] = 'Failed to create {0} cache cluster.'.format(name)

    if check_update:
        # Refresh this in case we're updating from 'only_on_modify' above...
        updated = __salt__['boto3_elasticache.'
                           'describe_cache_clusters'](name, region=region, key=key,
                                                      keyid=keyid, profile=profile)
        need_update = _diff_cache_cluster(updated['CacheClusters'][0], args)
        if need_update:
            if __opts__['test']:
                ret['comment'] = 'Cache cluster {0} would be modified.'.format(name)
                ret['result'] = None
                return ret
            modified = __salt__['boto3_elasticache.'
                                'modify_cache_cluster'](name, wait=wait,
                                                        security_groups=security_groups,
                                                        region=region, key=key, keyid=keyid,
                                                        profile=profile, **need_update)
            if modified:
                new = __salt__['boto3_elasticache.'
                               'describe_cache_clusters'](name, region=region, key=key,
                                                          keyid=keyid, profile=profile)
                if ret['comment']:  # 'create' just ran...
                    ret['comment'] += ' ... and then immediately modified.'
                else:
                    ret['comment'] = 'Cache cluster {0} was modified.'.format(name)
                    ret['changes']['old'] = current
                ret['changes']['new'] = new[0]
            else:
                ret['result'] = False
                ret['comment'] = 'Failed to modify cache cluster {0}.'.format(name)
        else:
            ret['comment'] = 'Cache cluster {0} is in the desired state.'.format(name)
    return ret