예제 #1
0
    def execute(self, context: 'Context') -> None:
        hook = CloudSQLHook(
            gcp_conn_id=self.gcp_conn_id,
            api_version=self.api_version,
            impersonation_chain=self.impersonation_chain,
        )
        self._validate_body_fields()
        if not self._check_if_instance_exists(self.instance, hook):
            hook.create_instance(project_id=self.project_id, body=self.body)
        else:
            self.log.info(
                "Cloud SQL instance with ID %s already exists. Aborting create.",
                self.instance)

        CloudSQLInstanceLink.persist(
            context=context,
            task_instance=self,
            cloud_sql_instance=self.instance,
            project_id=self.project_id or hook.project_id,
        )

        instance_resource = hook.get_instance(project_id=self.project_id,
                                              instance=self.instance)
        service_account_email = instance_resource["serviceAccountEmailAddress"]
        task_instance = context['task_instance']
        task_instance.xcom_push(key="service_account_email",
                                value=service_account_email)
예제 #2
0
 def execute(self, context: 'Context') -> None:
     self._validate_body_fields()
     hook = CloudSQLHook(
         gcp_conn_id=self.gcp_conn_id,
         api_version=self.api_version,
         impersonation_chain=self.impersonation_chain,
     )
     CloudSQLInstanceLink.persist(
         context=context,
         task_instance=self,
         cloud_sql_instance=self.instance,
         project_id=self.project_id or hook.project_id,
     )
     FileDetailsLink.persist(
         context=context,
         task_instance=self,
         uri=self.body["importContext"]["uri"][5:],
         project_id=self.project_id or hook.project_id,
     )
     return hook.import_instance(project_id=self.project_id, instance=self.instance, body=self.body)
예제 #3
0
    def execute(self, context: 'Context'):
        hook = CloudSQLHook(
            gcp_conn_id=self.gcp_conn_id,
            api_version=self.api_version,
            impersonation_chain=self.impersonation_chain,
        )
        if not self._check_if_instance_exists(self.instance, hook):
            raise AirflowException(
                f'Cloud SQL instance with ID {self.instance} does not exist. '
                'Please specify another instance to patch.'
            )
        else:
            CloudSQLInstanceLink.persist(
                context=context,
                task_instance=self,
                cloud_sql_instance=self.instance,
                project_id=self.project_id or hook.project_id,
            )

            return hook.patch_instance(project_id=self.project_id, body=self.body, instance=self.instance)
예제 #4
0
class CloudSQLImportInstanceOperator(CloudSQLBaseOperator):
    """
    Imports data into a Cloud SQL instance from a SQL dump or CSV file in Cloud Storage.

    CSV IMPORT:

    This operator is NOT idempotent for a CSV import. If the same file is imported
    multiple times, the imported data will be duplicated in the database.
    Moreover, if there are any unique constraints the duplicate import may result in an
    error.

    SQL IMPORT:

    This operator is idempotent for a SQL import if it was also exported by Cloud SQL.
    The exported SQL contains 'DROP TABLE IF EXISTS' statements for all tables
    to be imported.

    If the import file was generated in a different way, idempotence is not guaranteed.
    It has to be ensured on the SQL file level.

    .. seealso::
        For more information on how to use this operator, take a look at the guide:
        :ref:`howto/operator:CloudSQLImportInstanceOperator`

    :param instance: Cloud SQL instance ID. This does not include the project ID.
    :param body: The request body, as described in
        https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances/import#request-body
    :param project_id: Optional, Google Cloud Project ID. If set to None or missing,
            the default project_id from the Google Cloud connection is used.
    :param gcp_conn_id: The connection ID used to connect to Google Cloud.
    :param api_version: API version used (e.g. v1beta4).
    :param validate_body: Whether the body should be validated. Defaults to True.
    :param impersonation_chain: Optional service account to impersonate using short-term
        credentials, or chained list of accounts required to get the access_token
        of the last account in the list, which will be impersonated in the request.
        If set as a string, the account must grant the originating account
        the Service Account Token Creator IAM role.
        If set as a sequence, the identities from the list must grant
        Service Account Token Creator IAM role to the directly preceding identity, with first
        account from the list granting this role to the originating account (templated).
    """

    # [START gcp_sql_import_template_fields]
    template_fields: Sequence[str] = (
        'project_id',
        'instance',
        'body',
        'gcp_conn_id',
        'api_version',
        'impersonation_chain',
    )
    # [END gcp_sql_import_template_fields]
    ui_color = '#D3EDFB'
    operator_extra_links = (CloudSQLInstanceLink(), FileDetailsLink())

    def __init__(
        self,
        *,
        instance: str,
        body: dict,
        project_id: Optional[str] = None,
        gcp_conn_id: str = 'google_cloud_default',
        api_version: str = 'v1beta4',
        validate_body: bool = True,
        impersonation_chain: Optional[Union[str, Sequence[str]]] = None,
        **kwargs,
    ) -> None:
        self.body = body
        self.validate_body = validate_body
        super().__init__(
            project_id=project_id,
            instance=instance,
            gcp_conn_id=gcp_conn_id,
            api_version=api_version,
            impersonation_chain=impersonation_chain,
            **kwargs,
        )

    def _validate_inputs(self) -> None:
        super()._validate_inputs()
        if not self.body:
            raise AirflowException("The required parameter 'body' is empty")

    def _validate_body_fields(self) -> None:
        if self.validate_body:
            GcpBodyFieldValidator(CLOUD_SQL_IMPORT_VALIDATION,
                                  api_version=self.api_version).validate(
                                      self.body)

    def execute(self, context: 'Context') -> None:
        self._validate_body_fields()
        hook = CloudSQLHook(
            gcp_conn_id=self.gcp_conn_id,
            api_version=self.api_version,
            impersonation_chain=self.impersonation_chain,
        )
        CloudSQLInstanceLink.persist(
            context=context,
            task_instance=self,
            cloud_sql_instance=self.instance,
            project_id=self.project_id or hook.project_id,
        )
        FileDetailsLink.persist(
            context=context,
            task_instance=self,
            uri=self.body["importContext"]["uri"][5:],
            project_id=self.project_id or hook.project_id,
        )
        return hook.import_instance(project_id=self.project_id,
                                    instance=self.instance,
                                    body=self.body)
예제 #5
0
class CloudSQLInstancePatchOperator(CloudSQLBaseOperator):
    """
    Updates settings of a Cloud SQL instance.

    Caution: This is a partial update, so only included values for the settings will be
    updated.

    In the request body, supply the relevant portions of an instance resource, according
    to the rules of patch semantics.
    https://cloud.google.com/sql/docs/mysql/admin-api/how-tos/performance#patch

    .. seealso::
        For more information on how to use this operator, take a look at the guide:
        :ref:`howto/operator:CloudSQLInstancePatchOperator`

    :param body: Body required by the Cloud SQL patch API, as described in
        https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances/patch#request-body
    :param instance: Cloud SQL instance ID. This does not include the project ID.
    :param project_id: Optional, Google Cloud Project ID.  If set to None or missing,
            the default project_id from the Google Cloud connection is used.
    :param gcp_conn_id: The connection ID used to connect to Google Cloud.
    :param api_version: API version used (e.g. v1beta4).
    :param impersonation_chain: Optional service account to impersonate using short-term
        credentials, or chained list of accounts required to get the access_token
        of the last account in the list, which will be impersonated in the request.
        If set as a string, the account must grant the originating account
        the Service Account Token Creator IAM role.
        If set as a sequence, the identities from the list must grant
        Service Account Token Creator IAM role to the directly preceding identity, with first
        account from the list granting this role to the originating account (templated).
    """

    # [START gcp_sql_patch_template_fields]
    template_fields: Sequence[str] = (
        'project_id',
        'instance',
        'body',
        'gcp_conn_id',
        'api_version',
        'impersonation_chain',
    )
    # [END gcp_sql_patch_template_fields]
    ui_color = '#FBDAC8'
    operator_extra_links = (CloudSQLInstanceLink(), )

    def __init__(
        self,
        *,
        body: dict,
        instance: str,
        project_id: Optional[str] = None,
        gcp_conn_id: str = 'google_cloud_default',
        api_version: str = 'v1beta4',
        impersonation_chain: Optional[Union[str, Sequence[str]]] = None,
        **kwargs,
    ) -> None:
        self.body = body
        super().__init__(
            project_id=project_id,
            instance=instance,
            gcp_conn_id=gcp_conn_id,
            api_version=api_version,
            impersonation_chain=impersonation_chain,
            **kwargs,
        )

    def _validate_inputs(self) -> None:
        super()._validate_inputs()
        if not self.body:
            raise AirflowException("The required parameter 'body' is empty")

    def execute(self, context: 'Context'):
        hook = CloudSQLHook(
            gcp_conn_id=self.gcp_conn_id,
            api_version=self.api_version,
            impersonation_chain=self.impersonation_chain,
        )
        if not self._check_if_instance_exists(self.instance, hook):
            raise AirflowException(
                f'Cloud SQL instance with ID {self.instance} does not exist. '
                'Please specify another instance to patch.')
        else:
            CloudSQLInstanceLink.persist(
                context=context,
                task_instance=self,
                cloud_sql_instance=self.instance,
                project_id=self.project_id or hook.project_id,
            )

            return hook.patch_instance(project_id=self.project_id,
                                       body=self.body,
                                       instance=self.instance)
예제 #6
0
class CloudSQLCreateInstanceOperator(CloudSQLBaseOperator):
    """
    Creates a new Cloud SQL instance.
    If an instance with the same name exists, no action will be taken and
    the operator will succeed.

    .. seealso::
        For more information on how to use this operator, take a look at the guide:
        :ref:`howto/operator:CloudSQLCreateInstanceOperator`

    :param body: Body required by the Cloud SQL insert API, as described in
        https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances/insert
        #request-body
    :param instance: Cloud SQL instance ID. This does not include the project ID.
    :param project_id: Optional, Google Cloud Project ID. If set to None or missing,
            the default project_id from the Google Cloud connection is used.
    :param gcp_conn_id: The connection ID used to connect to Google Cloud.
    :param api_version: API version used (e.g. v1beta4).
    :param validate_body: True if body should be validated, False otherwise.
    :param impersonation_chain: Optional service account to impersonate using short-term
        credentials, or chained list of accounts required to get the access_token
        of the last account in the list, which will be impersonated in the request.
        If set as a string, the account must grant the originating account
        the Service Account Token Creator IAM role.
        If set as a sequence, the identities from the list must grant
        Service Account Token Creator IAM role to the directly preceding identity, with first
        account from the list granting this role to the originating account (templated).
    """

    # [START gcp_sql_create_template_fields]
    template_fields: Sequence[str] = (
        'project_id',
        'instance',
        'body',
        'gcp_conn_id',
        'api_version',
        'impersonation_chain',
    )
    # [END gcp_sql_create_template_fields]
    ui_color = '#FADBDA'
    operator_extra_links = (CloudSQLInstanceLink(), )

    def __init__(
        self,
        *,
        body: dict,
        instance: str,
        project_id: Optional[str] = None,
        gcp_conn_id: str = 'google_cloud_default',
        api_version: str = 'v1beta4',
        validate_body: bool = True,
        impersonation_chain: Optional[Union[str, Sequence[str]]] = None,
        **kwargs,
    ) -> None:
        self.body = body
        self.validate_body = validate_body
        super().__init__(
            project_id=project_id,
            instance=instance,
            gcp_conn_id=gcp_conn_id,
            api_version=api_version,
            impersonation_chain=impersonation_chain,
            **kwargs,
        )

    def _validate_inputs(self) -> None:
        super()._validate_inputs()
        if not self.body:
            raise AirflowException("The required parameter 'body' is empty")

    def _validate_body_fields(self) -> None:
        if self.validate_body:
            GcpBodyFieldValidator(CLOUD_SQL_CREATE_VALIDATION,
                                  api_version=self.api_version).validate(
                                      self.body)

    def execute(self, context: 'Context') -> None:
        hook = CloudSQLHook(
            gcp_conn_id=self.gcp_conn_id,
            api_version=self.api_version,
            impersonation_chain=self.impersonation_chain,
        )
        self._validate_body_fields()
        if not self._check_if_instance_exists(self.instance, hook):
            hook.create_instance(project_id=self.project_id, body=self.body)
        else:
            self.log.info(
                "Cloud SQL instance with ID %s already exists. Aborting create.",
                self.instance)

        CloudSQLInstanceLink.persist(
            context=context,
            task_instance=self,
            cloud_sql_instance=self.instance,
            project_id=self.project_id or hook.project_id,
        )

        instance_resource = hook.get_instance(project_id=self.project_id,
                                              instance=self.instance)
        service_account_email = instance_resource["serviceAccountEmailAddress"]
        task_instance = context['task_instance']
        task_instance.xcom_push(key="service_account_email",
                                value=service_account_email)