
    VhQ                     L   d Z dZdZddlZddlZddlZ	 ddlZddlm	Z	 ddl
mZ ddlmZ ddlmZ d	d
gZg dZdZdZdZ G d de      Z G d de      Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d  Z&d! Z'd" Z(d# Z)d$ Z*d% Z+e,d&k(  r e+        yy# e$ r Y w xY w)'aL  
---
module: data_pipeline
version_added: 1.0.0
author:
  - Raghu Udiyar (@raags) <raghusiddarth@gmail.com>
  - Sloane Hertel (@s-hertel) <shertel@redhat.com>
short_description: Create and manage AWS Datapipelines
description:
  - Create and manage AWS Datapipelines. Creation is not idempotent in AWS, so the C(uniqueId) is created by hashing the options (minus objects)
    given to the datapipeline.
  - The pipeline definition must be in the format given here
    U(https://docs.aws.amazon.com/datapipeline/latest/APIReference/API_PutPipelineDefinition.html#API_PutPipelineDefinition_RequestSyntax).
  - Operations will wait for a configurable amount of time to ensure the pipeline is in the requested state.
options:
  name:
    description:
      - The name of the Datapipeline to create/modify/delete.
    required: true
    type: str
  description:
    description:
      - An optional description for the pipeline being created.
    default: ''
    type: str
  objects:
    type: list
    elements: dict
    default: []
    description:
      - A list of pipeline object definitions, each of which is a dict that takes the keys I(id), I(name) and I(fields).
    suboptions:
      id:
        description:
          - The ID of the object.
        type: str
      name:
        description:
          - The name of the object.
        type: str
      fields:
        description:
          - Key-value pairs that define the properties of the object.
          - The value is specified as a reference to another object I(refValue) or as a string value I(stringValue)
            but not as both.
        type: list
        elements: dict
        suboptions:
          key:
            type: str
            description:
              - The field identifier.
          stringValue:
            type: str
            description:
              - The field value.
              - Exactly one of I(stringValue) and I(refValue) may be specified.
          refValue:
            type: str
            description:
              - The field value, expressed as the identifier of another object.
              - Exactly one of I(stringValue) and I(refValue) may be specified.
  parameters:
    description:
      - A list of parameter objects (dicts) in the pipeline definition.
    type: list
    elements: dict
    default: []
    suboptions:
      id:
        description:
          - The ID of the parameter object.
      attributes:
        description:
          - A list of attributes (dicts) of the parameter object.
        type: list
        elements: dict
        suboptions:
          key:
            description: The field identifier.
            type: str
          stringValue:
            description: The field value.
            type: str

  values:
    description:
      - A list of parameter values (dicts) in the pipeline definition.
    type: list
    elements: dict
    default: []
    suboptions:
      id:
        description: The ID of the parameter value
        type: str
      stringValue:
        description: The field value
        type: str
  timeout:
    description:
      - Time in seconds to wait for the pipeline to transition to the requested state, fail otherwise.
    default: 300
    type: int
  state:
    description:
      - The requested state of the pipeline.
    choices: ['present', 'absent', 'active', 'inactive']
    default: present
    type: str
  tags:
    description:
      - A dict of key:value pair(s) to add to the pipeline.
    type: dict
    default: {}
    aliases: ['resource_tags']
extends_documentation_fragment:
  - amazon.aws.common.modules
  - amazon.aws.region.modules
  - amazon.aws.boto3
a  
# Note: These examples do not set authentication details, see the AWS Guide for details.

# Create pipeline
- community.aws.data_pipeline:
    name: test-dp
    region: us-west-2
    objects: "{{pipelineObjects}}"
    parameters: "{{pipelineParameters}}"
    values: "{{pipelineValues}}"
    tags:
      key1: val1
      key2: val2
    state: present

# Example populating and activating a pipeline that demonstrates two ways of providing pipeline objects
- community.aws.data_pipeline:
  name: test-dp
  objects:
    - id: "DefaultSchedule"
      name: "Every 1 day"
      fields:
        - "key": "period"
          "stringValue": "1 days"
        - "key": "type"
          "stringValue": "Schedule"
        - "key": "startAt"
          "stringValue": "FIRST_ACTIVATION_DATE_TIME"
    - id: "Default"
      name: "Default"
      fields:
        - "key": "resourceRole"
          "stringValue": "my_resource_role"
        - "key": "role"
          "stringValue": "DataPipelineDefaultRole"
        - "key": "pipelineLogUri"
          "stringValue": "s3://my_s3_log.txt"
        - "key": "scheduleType"
          "stringValue": "cron"
        - "key": "schedule"
          "refValue": "DefaultSchedule"
        - "key": "failureAndRerunMode"
          "stringValue": "CASCADE"
  state: active

# Activate pipeline
- community.aws.data_pipeline:
    name: test-dp
    region: us-west-2
    state: active

# Delete pipeline
- community.aws.data_pipeline:
    name: test-dp
    region: us-west-2
    state: absent
a  
changed:
  description: whether the data pipeline has been modified
  type: bool
  returned: always
  sample:
    changed: true
result:
  description:
    - Contains the data pipeline data (data_pipeline) and a return message (msg).
      If the data pipeline exists data_pipeline will contain the keys description, name,
      pipeline_id, state, tags, and unique_id. If the data pipeline does not exist then
      data_pipeline will be an empty dict. The msg describes the status of the operation.
  returned: always
  type: dict
    N)to_text)camel_dict_to_snake_dict)is_boto3_error_code)AnsibleCommunityAWSModuleACTIVE	SCHEDULED)INACTIVEPENDINGFINISHEDDELETING
ACTIVATINGDEACTIVATINGz(^.*Pipeline with id: {0} does not exist$c                       e Zd Zy)DataPipelineNotFoundN__name__
__module____qualname__     o/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/modules/data_pipeline.pyr   r          r   r   c                       e Zd Zy)TimeOutExceptionNr   r   r   r   r   r      r   r   r   c                 `    | j                         }|d   D ]  }|d   |k(  s|d   c S  t        )zReturn pipeline id for the given pipeline name

    :param object client: boto3 datapipeline client
    :param string name: pipeline name
    :returns: pipeline id
    :raises: DataPipelineNotFound

    pipelineIdListnameid)list_pipelinesr   )clientr   	pipelinesdps       r   pipeline_idr#      sD     %%'I() f:d8O r   c                 ^    	 | j                  |g      S # t        ddg      $ r t        w xY w)zReturn pipeline description list

    :param object client: boto3 datapipeline client
    :returns: pipeline description dictionary
    :raises: DataPipelineNotFound

    )pipelineIdsPipelineNotFoundExceptionPipelineDeletedException)describe_pipelinesr   r   r    dp_ids     r   pipeline_descriptionr+      s>    #((eW(== ;=WXY #""#s    ,c                 v    t        | |      }|d   d   d   D ]  }|d   |k(  s|d   c S  t        d| d      )a6  Return a pipeline field from the pipeline description.

    The available fields are listed in describe_pipelines output.

    :param object client: boto3 datapipeline client
    :param string dp_id: pipeline id
    :param string field: pipeline description field
    :returns: pipeline field information

    pipelineDescriptionListr   fieldskeystringValuez
Field key z not found!)r+   KeyError)r    r*   fielddp_description	field_keys        r   pipeline_fieldr5     s]     *&%8N#$=>qA(K ,	Uu$]++, Zwk2
33r   c                 r    t        | dz        D ]!  } ||i |r yt        j                  d       # t        )a  Run func with the provided args and kwargs, and wait until
    timeout for truthy return value

    :param int timeout: time to wait for status
    :param function func: function to run, should return True or False
    :param args func_args: function args to pass to func
    :param kwargs func_kwargs: function key word args
    :returns: True if func returns truthy within timeout
    :raises: TimeOutException

    
   T)rangetimesleepr   )timeoutfunc	func_argsfunc_kwargscounts        r   run_with_timeoutr@     sA     w"}% *k* JJrN r   c                 L    	 t        t        | |            S # t        $ r Y yw xY w)zCheck if datapipeline exists

    :param object client: boto3 datapipeline client
    :param string dp_id: pipeline id
    :returns: True or False

    F)boolr+   r   r)   s     r   check_dp_existsrC   1  s,    (788 s    	##c                 h    t        |t              s
t               t        t	        | |d      |v       S )zChecks if datapipeline matches states in status list

    :param object client: boto3 datapipeline client
    :param string dp_id: pipeline id
    :param list status: list of states to check against
    :returns: True or False

    @pipelineStater2   )
isinstancelistAssertionErrorrB   r5   )r    r*   statuss      r   check_dp_statusrK   @  s1     fd#vu4DEOPPr   c                 .    | ||f}t        |t        g| S N)r@   rK   )r    r*   rJ   r;   argss        r   pipeline_status_timeoutrO   N  s     E6"DG_<t<<r   c                 ,    | |f}t        |t        g| S rM   )r@   rC   )r    r*   r;   rN   s       r   pipeline_exists_timeoutrQ   S  s    E?DG_<t<<r   c                 D   |j                   j                  d      }|j                   j                  d      }	 t        | |      }t        | d      t        v rd}n)	 | j                  |	       	 t        | |t        |       d}t        | |      }|d| dd}||fS # t        $ r |j	                  d| d       Y zw xY w# t        d
      $ r |j	                  d       Y vw xY w# t        $ r. t        | |d      dk(  rn|j	                  d| d| d       Y w xY w)zActivates pipeliner   r;   Data Pipeline 
 not foundmsgrE   rF   F
pipelineIdInvalidRequestExceptionz5You need to populate your pipeline before activation.rJ   r;   r   z# failed to activate within timeout  secondsTz activated.data_pipelinerV   )paramsgetr#   r   	fail_jsonr5   DP_ACTIVE_STATESactivate_pipeliner   rO   r   
get_resultr    moduledp_namer;   r*   changedr]   results           r   rb   rb   X  s^   mm'Gmm	*GCFG, fe+;<@PP	Z$$$6		#FE:JT[\ vu-M&y4F
 V9   C~gYjABC ##<= 	Z!XY	Z   	fe3CD
R  (	1TU\T]]ef ! 	s5   B C /C( B?>B? C%$C%(4DDc                    |j                   j                  d      }|j                   j                  d      }	 t        | |      }t        | d      t        v rd}n(| j                  |	       	 t        | |t        |
       d}t        | |      }|d| dd}||fS # t        $ r |j	                  d| d       Y yw xY w# t        $ r |j	                  d| d| d       Y dw xY w)zDeactivates pipeliner   r;   rS   rT   rU   rE   rF   FrW   rZ   z% failed to deactivate within timeout r[   Tz deactivated.r\   )r^   r_   r#   r   r`   r5   DP_INACTIVE_STATESdeactivate_pipelinerO   r   rc   rd   s           r   rk   rk   ~  s   mm'Gmm	*GCFG, fe+;<@RR""e"4	#FE:LV]^
 vu-M&y6F
 V+   C~gYjABC   	$WI-RSZR[[cd  	s#   B .C B>=B>"C&%C&c                 p    |j                  |        	 t        || t        g|       y # t        $ r Y yw xY w)NrW   )r    r*   rJ   r;   T)delete_pipelinerO   PIPELINE_DOESNT_EXISTr   )r*   r    r;   s      r   _delete_dp_with_checkro     s=    
e,vUDYCZdkl s   ) 	55c                 (   |j                   j                  d      }|j                   j                  d      }	 t        | |      }t        || |       d}i d| d	d
}|fS # t        $ r d}Y t
        $ r |j                  d| d| d       Y =w xY w)zDeletes pipeliner   r;   TFrS   z! failed to delete within timeout r[   rU   z deletedr\   )r^   r_   r#   ro   r   r   r`   )r    re   rf   r;   r*   rg   rh   s          r   rm   rm     s    mm'Gmm	*G	
FG,eVW5 y1F
 V    
 	)J7)S[\ 	 	

s   A   B-!BBc                    t        | j                        }dD cg c]  }|j                  |d        c} t        j                  |d      j                  d      }t        j                  |      j                         }|S c c}w )N)objectsr;   T)	sort_keyszutf-8)	dictr^   popjsondumpsencodehashlibmd5	hexdigest)re   dataeach	json_datahashed_datas        r   build_unique_idr     sf    D&<=dTXXdD=

44077@I++i(224K >s   Bc                 j    | j                         D cg c]  \  }}t        ||       c}}S c c}}w )zReformats tags

    :param dict tags: dict of data pipeline tags (e.g. {key1: val1, key2: val2, key3: val3})
    :returns: list of dicts (e.g. [{key: key1, value: val1}, {key: key2, value: val2}, {key: key3, value: val3}])

    )r/   value)itemsrt   )tagskvs      r   format_tagsr     s)     .2ZZ\:TQDQa :::s   /c                     t        | |      d   d   }t        | |d      |d<   t        | |d      |d<   |d= t        |      }|S )	zGet the current state of the data pipeline and reformat it to snake_case for exit_json

    :param object client: boto3 datapipeline client
    :param string dp_id: pipeline id
    :returns: reformatted dict of pipeline description

    r-   r   uniqueIdrF   	unique_idrE   pipeline_stater.   )r+   r5   r   )r    r*   r"   s      r   rc   rc     s^     
fe	,-F	G	JB %VU*EB{O)&%?OPB 	8
 
""	%BIr   c                 2   i }d}d}t        |      }	 t        | |      }t        t        | |d            }	|	|k7  rd}d}nC| j	                  |      d   }
|
|k7  rt        | |||      \  }}nd| d	}t        | |      }||d
}|||fS # t        $ r d}Y w xY w)zmCheck if there's another pipeline with the same unique_id and if so, checks if the object needs to be updatedFr   rF   NEW_VERSIONTrW   pipelineObjectsrS   z is presentr\   )r   r#   r   r5   get_pipeline_definitiondefine_pipelinerc   r   )r    re   rr   r   rf   rh   rg   	create_dpr*   dp_unique_id
dp_objectsrV   r]   s                r   diff_pipeliner     s    FGI  'IFG,~fe:NO9$#GI  7757IJ[\JW$.vvwN 'wi{;&vu5M!.F gv%%   	s   A0B BBc                    |j                   j                  d      }t        | |d      dk(  rd| d}d}||fS |rX|j                   j                  d      }|j                   j                  d	      }	 | j                  ||||
       d| d}d}||fS d}d}||fS # t        j
                  j                  t        j
                  j                  f$ r$}	|j                  |	d| d       Y d}	~	fS d}	~	ww xY w)zPuts pipeline definitionr   rE   rF   r   rS   z1 is unable to be updated while in state FINISHED.F
parametersvalues)rX   r   parameterObjectsparameterValuesz has been updated.Tz*Failed to put the definition for pipeline z. Check that string/reference fieldsare not empty and that the number of objects in the pipeline does not exceed maximum allowedobjectsrU   N )	r^   r_   r5   put_pipeline_definitionbotocore
exceptionsClientErrorBotoCoreErrorfail_json_aws)
r    re   rr   r*   rf   rV   rg   r   r   es
             r   r   r     s7   mm'Gfe+;<
Jwi'XY2 C</ 
]]&&|4
""8,	** 'Jhn +  #7)+=>CG C< C< ##//1D1D1R1RS 	  @	 J  !   C<	s   2B 7C6C11C6c                 <   |j                   j                  d      }|j                   j                  dd      }|j                   j                  dd      }|j                   j                  d      }|j                   j                  d      }t        |      }t        | ||||      \  }}	}
|	dk(  rt	        | |      \  }	}|r^	 t        |      }| j                  ||||	      }|d
   }t        | ||       t        | ||      \  }	}d}	t!        | |      }|d| d|z   d}
|	|
fS # t        $ r |j                  d| d| d       Y St        j                  j                  t        j                  j                  f$ r!}|j                  |d| d       Y d}~d}~ww xY w)z;Creates datapipeline. Uses uniqueId to achieve idempotency.r   rr   Ndescriptionr   r   r;   r   )r   r   r   r   rX   rS   z! failed to create within timeout r[   rU   z#Failed to create the data pipeline .Tz	 created.r\   )r^   r_   r   r   rm   r   create_pipelinerQ   r   r`   r   r   r   r   r   r   rc   )r    re   rf   rr   r   r   r;   r   r   rg   rh   creation_resultr"   r*   r   rV   r]   s                    r   r   r   .  s   mm'Gmm	40G--##M26K==V$Dmm	*G'I!.vvw	SZ![Iw-#266#B  	t$D''WyVahl'mB|$E#FE7; 'vvwF"651*#G9I6<

 V'   	$WI-NwiW_`   ##//1D1D1R1RS 	  9'!D !  	s   ?2D   "F6F:FFc                     t        t        d      t        dd      t        ddg d      t        ddg d      t        dd	d
      t        dg d      t        ddi dg      t        ddg d            } t        | d      }	 |j                  d      }|j                  j                  d      }|dk(  rt        |      \  }}n>|dk(  rt        |      \  }}n)|dk(  rt        |      \  }}n|dk(  rt        |      \  }}|j                         y # t        j                  j
                  t        j                  j                  f$ r}|j                  |d       Y d }~d }~ww xY w)NT)requiredFr   )r   defaultrH   rt   )r   typer   elementsinti,  )r   r   r   present)r   absentactiveinactive)r   choicesresource_tags)r   r   r   aliases)r   r   rr   r   r;   stater   r   )argument_specsupports_check_modedatapipelinezFailed to connect to AWSrU   r   r   r   r   )rh   rg   )rt   AnsibleAWSModuler    r   r   r   r   r   r^   r_   r   rm   rb   rk   	exit_json)r   re   r    r   r   rg   rh   s          r   mainr   [  sc   4 %4e&"vNVR&Qe%=9.YZ5vrOCTUUfM	M MuUF@~. MMg&E	)&&9	(	)&&9	(	+FF;	*	-ff=
FG4 ++X-@-@-N-NO @Q$>??@s   D 7E,E''E,__main__)-DOCUMENTATIONEXAMPLESRETURNry   rv   r9   r   ImportErroransible.module_utils._textr   0ansible.module_utils.common.dict_transformationsr   <ansible_collections.amazon.aws.plugins.module_utils.botocorer   >ansible_collections.community.aws.plugins.module_utils.modulesr   r   ra   rj   DP_ACTIVATING_STATEDP_DEACTIVATING_STATErn   	Exceptionr   r   r#   r+   r5   r@   rC   rK   rO   rQ   rb   rk   ro   rm   r   r   rc   r   r   r   r   r   r   r   r   <module>r      s  wr8t
"   	 / U \ xk* D " & B 	9 		y 	 #4$.Q=
=
#L>.;4 &FD*Z5> zF S  		s   B B#"B#