Esempio n. 1
0
    def Run(self, args):
        """Displays configuration and metadata about a Cloud SQL instance.

    Information such as instance name, IP address, region, the CA certificate
    and configuration settings will be displayed.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      A dict object representing the instance resource if fetching the instance
      was successful.
    Raises:
      HttpException: A http error response was received while executing api
          request.
    ResourceNotFoundError: The SQL instance was not found.
    """
        client = api_util.SqlClient(api_util.API_VERSION_DEFAULT)
        sql_client = client.sql_client
        sql_messages = client.sql_messages

        validate.ValidateInstanceName(args.instance)
        instance_ref = client.resource_parser.Parse(
            args.instance,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='sql.instances')

        try:
            instance = sql_client.instances.Get(
                sql_messages.SqlInstancesGetRequest(
                    project=instance_ref.project,
                    instance=instance_ref.instance))
            instance.state = instance_api_util.GetInstanceState(instance)
            # TODO(b/122660263): Remove when V1 instances are no longer supported.
            if instance_api_util.IsInstanceV1(instance):
                instance_command_util.ShowV1DeprecationWarning()
            return instance
        except apitools_exceptions.HttpError as error:
            if error.status_code == six.moves.http_client.FORBIDDEN:
                raise exceptions.ResourceNotFoundError(
                    'There was no instance found at {} or you are not authorized to '
                    'access it.'.format(instance_ref.RelativeName()))
            raise calliope_exceptions.HttpException(error)
Esempio n. 2
0
def RunBaseCreateCommand(args, release_track):
    """Creates a new Cloud SQL instance.

  Args:
    args: argparse.Namespace, The arguments that this command was invoked
        with.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the create
    operation if the create was successful.
  Raises:
    HttpException: A http error response was received while executing api
        request.
  """
    client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT)
    sql_client = client.sql_client
    sql_messages = client.sql_messages

    validate.ValidateInstanceName(args.instance)
    instance_ref = client.resource_parser.Parse(
        args.instance,
        params={'project': properties.VALUES.core.project.GetOrFail},
        collection='sql.instances')

    # Get the region, tier, and database version from the main if these fields
    # are not specified.
    # TODO(b/64266672): Remove once API does not require these fields.
    if args.IsSpecified('main_instance_name'):
        main_instance_ref = client.resource_parser.Parse(
            args.main_instance_name,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='sql.instances')
        try:
            main_instance_resource = sql_client.instances.Get(
                sql_messages.SqlInstancesGetRequest(
                    project=instance_ref.project,
                    instance=main_instance_ref.instance))
        except apitools_exceptions.HttpError as error:
            # TODO(b/64292220): Remove once API gives helpful error message.
            log.debug('operation : %s', str(main_instance_ref))
            exc = exceptions.HttpException(error)
            if resource_property.Get(
                    exc.payload.content,
                    resource_lex.ParseKey('error.errors[0].reason'),
                    None) == 'notAuthorized':
                msg = (
                    'You are either not authorized to access the main instance or '
                    'it does not exist.')
                raise exceptions.HttpException(msg)
            raise
        if not args.IsSpecified('region'):
            args.region = main_instance_resource.region
        if not args.IsSpecified('database_version'):
            args.database_version = main_instance_resource.databaseVersion
        if not args.IsSpecified('tier') and main_instance_resource.settings:
            args.tier = main_instance_resource.settings.tier
        # Check for CMEK usage; warn the user about replica inheriting the setting.
        if main_instance_resource.diskEncryptionConfiguration:
            command_util.ShowCmekWarning('replica', 'the main instance')

    instance_resource = (
        command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs(
            sql_messages,
            args,
            instance_ref=instance_ref,
            release_track=release_track))

    # TODO(b/122660263): Remove when V1 instances are no longer supported.
    # V1 instances are deprecated. Prompt to continue if one is being created.
    if api_util.IsInstanceV1(instance_resource):
        log.warning(
            'First Generation instances will be automatically upgraded '
            'to Second Generation starting March 4th, 2020, and First Generation '
            'will be fully decommissioned on March 25, 2020. We recommend you '
            'create a Second Generation instance.')
        console_io.PromptContinue(cancel_on_no=True)

    if args.pricing_plan == 'PACKAGE':
        console_io.PromptContinue(
            'Charges will begin accruing immediately. Really create Cloud '
            'SQL instance?',
            cancel_on_no=True)

    operation_ref = None
    try:
        result_operation = sql_client.instances.Insert(instance_resource)

        operation_ref = client.resource_parser.Create(
            'sql.operations',
            operation=result_operation.name,
            project=instance_ref.project)

        if args. async:
            if not args.IsSpecified('format'):
                args.format = 'default'
            return sql_client.operations.Get(
                sql_messages.SqlOperationsGetRequest(
                    project=operation_ref.project,
                    operation=operation_ref.operation))

        operations.OperationsV1Beta4.WaitForOperation(
            sql_client, operation_ref, 'Creating Cloud SQL instance')

        log.CreatedResource(instance_ref)

        new_resource = sql_client.instances.Get(
            sql_messages.SqlInstancesGetRequest(
                project=instance_ref.project, instance=instance_ref.instance))
        return new_resource
    except apitools_exceptions.HttpError as error:
        log.debug('operation : %s', str(operation_ref))
        exc = exceptions.HttpException(error)
        if resource_property.Get(
                exc.payload.content,
                resource_lex.ParseKey('error.errors[0].reason'),
                None) == 'errorMaxInstancePerLabel':
            msg = resource_property.Get(exc.payload.content,
                                        resource_lex.ParseKey('error.message'),
                                        None)
            raise exceptions.HttpException(msg)
        raise
 def testBlankTierInstance(self):
     instance = data.GetV2Instance(self.project, self.instance)
     instance.settings.tier = None
     self.assertFalse(instances_util.IsInstanceV1(self.messages, instance))
 def testNonV1TierInstance(self):
     instance = data.GetV2Instance(self.project, self.instance)
     instance.backendType = None
     instance.settings.tier = 'db-n1-standard-1'
     self.assertFalse(instances_util.IsInstanceV1(self.messages, instance))
 def testV1TierInstance(self):
     instance = data.GetV1Instance(self.project, self.instance)
     instance.backendType = None
     instance.settings.tier = 'D0'
     self.assertTrue(instances_util.IsInstanceV1(self.messages, instance))
 def testPostgresInstance(self):
     self.assertFalse(
         instances_util.IsInstanceV1(
             self.messages,
             data.GetPostgresInstance(self.project, self.instance)))
 def testV2MySqlInstance(self):
     self.assertFalse(
         instances_util.IsInstanceV1(
             self.messages, data.GetV2Instance(self.project,
                                               self.instance)))
Esempio n. 8
0
def RunBasePatchCommand(args, release_track):
    """Updates settings of a Cloud SQL instance using the patch api method.

  Args:
    args: argparse.Namespace, The arguments that this command was invoked with.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the patch
    operation if the patch was successful.
  Raises:
    CancelledError: The user chose not to continue.
  """
    if args.diff and not args.IsSpecified('format'):
        args.format = 'diff(old, new)'

    client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT)
    sql_client = client.sql_client
    sql_messages = client.sql_messages

    validate.ValidateInstanceName(args.instance)
    instance_ref = client.resource_parser.Parse(
        args.instance,
        params={'project': properties.VALUES.core.project.GetOrFail},
        collection='sql.instances')

    # If --authorized-networks is used, confirm that the user knows the networks
    # will get overwritten.
    if args.authorized_networks:
        api_util.InstancesV1Beta4.PrintAndConfirmAuthorizedNetworksOverwrite()

    original_instance_resource = sql_client.instances.Get(
        sql_messages.SqlInstancesGetRequest(project=instance_ref.project,
                                            instance=instance_ref.instance))

    patch_instance = command_util.InstancesV1Beta4.ConstructPatchInstanceFromArgs(
        sql_messages,
        args,
        original=original_instance_resource,
        release_track=release_track)
    patch_instance.project = instance_ref.project
    patch_instance.name = instance_ref.instance

    # TODO(b/122660263): Remove when V1 instances are no longer supported.
    # V1 deprecation notice.
    if api_util.IsInstanceV1(sql_messages, original_instance_resource):
        command_util.ShowV1DeprecationWarning()

    cleared_fields = _GetConfirmedClearedFields(args, patch_instance,
                                                original_instance_resource)
    # beta only
    if args.maintenance_window_any:
        cleared_fields.append('settings.maintenanceWindow')

    with sql_client.IncludeFields(cleared_fields):
        result_operation = sql_client.instances.Patch(
            sql_messages.SqlInstancesPatchRequest(
                databaseInstance=patch_instance,
                project=instance_ref.project,
                instance=instance_ref.instance))

    operation_ref = client.resource_parser.Create(
        'sql.operations',
        operation=result_operation.name,
        project=instance_ref.project)

    if args.async_:
        return sql_client.operations.Get(
            sql_messages.SqlOperationsGetRequest(
                project=operation_ref.project,
                operation=operation_ref.operation))

    operations.OperationsV1Beta4.WaitForOperation(
        sql_client, operation_ref, 'Patching Cloud SQL instance')

    log.UpdatedResource(instance_ref)

    changed_instance_resource = sql_client.instances.Get(
        sql_messages.SqlInstancesGetRequest(project=instance_ref.project,
                                            instance=instance_ref.instance))
    return _Result(changed_instance_resource, original_instance_resource)
Esempio n. 9
0
def RunBaseCreateCommand(args, release_track):
  """Creates a new Cloud SQL instance.

  Args:
    args: argparse.Namespace, The arguments that this command was invoked with.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the create
    operation if the create was successful.
  Raises:
    HttpException: A http error response was received while executing api
        request.
    RequiredArgumentException: A required argument was not supplied by the user,
      such as omitting --root-password on a SQL Server instance.
    ArgumentError: An argument supplied by the user was incorrect, such as
      attempting to create a V1 instance.
  """
  client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT)
  sql_client = client.sql_client
  sql_messages = client.sql_messages

  validate.ValidateInstanceName(args.instance)
  instance_ref = client.resource_parser.Parse(
      args.instance,
      params={'project': properties.VALUES.core.project.GetOrFail},
      collection='sql.instances')

  # Get the region, tier, and database version from the master if these fields
  # are not specified.
  # TODO(b/64266672): Remove once API does not require these fields.
  if args.IsSpecified('master_instance_name'):
    master_instance_ref = client.resource_parser.Parse(
        args.master_instance_name,
        params={'project': properties.VALUES.core.project.GetOrFail},
        collection='sql.instances')
    try:
      master_instance_resource = sql_client.instances.Get(
          sql_messages.SqlInstancesGetRequest(
              project=instance_ref.project,
              instance=master_instance_ref.instance))
    except apitools_exceptions.HttpError as error:
      # TODO(b/64292220): Remove once API gives helpful error message.
      log.debug('operation : %s', six.text_type(master_instance_ref))
      exc = exceptions.HttpException(error)
      if resource_property.Get(exc.payload.content,
                               resource_lex.ParseKey('error.errors[0].reason'),
                               None) == 'notAuthorized':
        msg = ('You are either not authorized to access the master instance or '
               'it does not exist.')
        raise exceptions.HttpException(msg)
      raise
    if not args.IsSpecified('region'):
      args.region = master_instance_resource.region
    if not args.IsSpecified('database_version'):
      args.database_version = master_instance_resource.databaseVersion.name
    if not args.IsSpecified('tier') and master_instance_resource.settings:
      args.tier = master_instance_resource.settings.tier
    # Check for CMEK usage; warn the user about replica inheriting the setting.
    if master_instance_resource.diskEncryptionConfiguration:
      command_util.ShowCmekWarning('replica', 'the master instance')

  # --root-password is required when creating SQL Server instances
  if args.IsSpecified('database_version') and args.database_version.startswith(
      'SQLSERVER') and not args.IsSpecified('root_password'):
    raise exceptions.RequiredArgumentException(
        '--root-password',
        '`--root-password` is required when creating SQL Server instances.')

  instance_resource = (
      command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs(
          sql_messages,
          args,
          instance_ref=instance_ref,
          release_track=release_track))

  # TODO(b/122660263): Remove when V1 instances are no longer supported.
  # V1 instances are deprecated.
  # Note that the exception type is intentionally vague because the user may not
  # have directly supplied the offending argument.  For example, creating a read
  # replica defaults its tier to that of its master.
  if api_util.IsInstanceV1(sql_messages, instance_resource):
    raise sql_exceptions.ArgumentError(
        'First Generation instances can no longer be created.')

  operation_ref = None
  try:
    result_operation = sql_client.instances.Insert(instance_resource)

    operation_ref = client.resource_parser.Create(
        'sql.operations',
        operation=result_operation.name,
        project=instance_ref.project)

    if args.async_:
      if not args.IsSpecified('format'):
        args.format = 'default'
      return sql_client.operations.Get(
          sql_messages.SqlOperationsGetRequest(
              project=operation_ref.project, operation=operation_ref.operation))

    operations.OperationsV1Beta4.WaitForOperation(
        sql_client,
        operation_ref,
        'Creating Cloud SQL instance',
        # TODO(b/138403566): Remove the override once we improve creation times.
        max_wait_seconds=680)

    log.CreatedResource(instance_ref)

    new_resource = sql_client.instances.Get(
        sql_messages.SqlInstancesGetRequest(
            project=instance_ref.project, instance=instance_ref.instance))
    return new_resource
  except apitools_exceptions.HttpError as error:
    log.debug('operation : %s', six.text_type(operation_ref))
    exc = exceptions.HttpException(error)
    if resource_property.Get(exc.payload.content,
                             resource_lex.ParseKey('error.errors[0].reason'),
                             None) == 'errorMaxInstancePerLabel':
      msg = resource_property.Get(exc.payload.content,
                                  resource_lex.ParseKey('error.message'), None)
      raise exceptions.HttpException(msg)
    raise
def RunBaseCloneCommand(args, release_track):
  """Clones a Cloud SQL instance.

  Args:
    args: argparse.Namespace, The arguments used to invoke this command.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the
    clone operation if the clone was successful.
  Raises:
    ArgumentError: The arguments are invalid for some reason.
  """

  client = api_util.SqlClient(api_util.API_VERSION_DEFAULT)
  sql_client = client.sql_client
  sql_messages = client.sql_messages

  source_instance_ref, destination_instance_ref = (
      _GetInstanceRefsFromArgs(args, client))

  request = sql_messages.SqlInstancesCloneRequest(
      project=source_instance_ref.project,
      instance=source_instance_ref.instance,
      instancesCloneRequest=sql_messages.InstancesCloneRequest(
          cloneContext=sql_messages.CloneContext(
              kind='sql#cloneContext',
              destinationInstanceName=destination_instance_ref.instance)))

  _UpdateRequestFromArgs(request, args, sql_messages, release_track)

  # Check if source is V1; raise error if so.
  # Check if source has customer-managed key; show warning if so.
  try:
    source_instance_resource = sql_client.instances.Get(
        sql_messages.SqlInstancesGetRequest(
            project=source_instance_ref.project,
            instance=source_instance_ref.instance))

    # TODO(b/122660263): Remove when V1 instances are no longer supported.
    if instance_util.IsInstanceV1(sql_messages, source_instance_resource):
      raise exceptions.ArgumentError(
          'First Generation instances can no longer be created.')
    if source_instance_resource.diskEncryptionConfiguration:
      command_util.ShowCmekWarning('clone', 'the source instance')
  except apitools_exceptions.HttpError:
    # This is for informational purposes, so don't throw an error if failure.
    pass

  result = sql_client.instances.Clone(request)

  operation_ref = client.resource_parser.Create(
      'sql.operations',
      operation=result.name,
      project=destination_instance_ref.project)

  if args.async_:
    if not args.IsSpecified('format'):
      args.format = 'default'
    return sql_client.operations.Get(
        sql_messages.SqlOperationsGetRequest(
            project=operation_ref.project, operation=operation_ref.operation))
  operations.OperationsV1Beta4.WaitForOperation(sql_client, operation_ref,
                                                'Cloning Cloud SQL instance')
  log.CreatedResource(destination_instance_ref)
  rsource = sql_client.instances.Get(
      sql_messages.SqlInstancesGetRequest(
          project=destination_instance_ref.project,
          instance=destination_instance_ref.instance))
  rsource.kind = None
  return rsource