Example #1
0
    def _get_gcloud_storage_args(self, sub_opts, gsutil_args,
                                 gcloud_storage_map):
        if gcloud_storage_map is None:
            raise exception.GcloudStorageTranslationError(
                'Command "{}" cannot be translated to gcloud storage because the'
                ' translation mapping is missing.'.format(self.command_name))
        args = []
        if isinstance(gcloud_storage_map.gcloud_command, str):
            args = gcloud_storage_map.gcloud_command.split()
        elif isinstance(gcloud_storage_map.gcloud_command, dict):
            # If a command has sub-commands, e.g gsutil pap set, gsutil pap get.
            # All the flags mapping must be present in the subcommand's map
            # because gsutil does not have command specific flags
            # if sub-commands are present.
            if gcloud_storage_map.flag_map:
                raise ValueError(
                    'Flags mapping should not be present at the top-level command if '
                    'a sub-command is used. Command: {}.'.format(
                        self.command_name))
            sub_command = gsutil_args[0]
            sub_opts, parsed_args = self.ParseSubOpts(
                args=gsutil_args[1:], should_update_sub_opts_and_args=False)
            return self._get_gcloud_storage_args(
                sub_opts, parsed_args,
                gcloud_storage_map.gcloud_command.get(sub_command))
        else:
            raise ValueError('Incorrect mapping found for "{}" command'.format(
                self.command_name))

        if sub_opts:
            for option, value in sub_opts:
                if option not in gcloud_storage_map.flag_map:
                    raise exception.GcloudStorageTranslationError(
                        'Command option "{}" cannot be translated to'
                        ' gcloud storage'.format(option))
                args.append(gcloud_storage_map.flag_map[option].gcloud_flag)
                if value != '':
                    # Empty string represents that the user did not passed in a value
                    # for the flag.
                    args.append(value)
        return args + gsutil_args
Example #2
0
def _get_gcloud_binary_path():
    # GCLOUD_BINARY_PATH is used for testing purpose only.
    # It helps to run the parity_check.py script directly without having
    # to build gcloud.
    gcloud_binary_path = os.environ.get('GCLOUD_BINARY_PATH')
    if gcloud_binary_path:
        return gcloud_binary_path

    cloudsdk_root = os.environ.get('CLOUDSDK_ROOT_DIR')
    if cloudsdk_root is None:
        raise exception.GcloudStorageTranslationError(
            'Requested to use "gcloud storage" but the gcloud binary path cannot'
            ' be found. This might happen if you attempt to use gsutil that was'
            ' not installed via Cloud SDK. You can manually set the'
            ' `CLOUDSDK_ROOT_DIR` environment variable to point to the'
            ' google-cloud-sdk installation directory to resolve the issue.'
            ' Alternatively, you can set `use_gcloud_storage=False` to disable'
            ' running the command using gcloud storage.')
    return os.path.join(cloudsdk_root, 'bin', 'gcloud')
Example #3
0
 def _translate_headers(self):
     """Translates gsutil headers to equivalent gcloud storage flags."""
     flags = []
     for header_key_raw, header_value in self.headers.items():
         header_key = header_key_raw.lower()
         if header_key == 'x-goog-api-version':
             # Gsutil adds this header. We don't have to translate it for gcloud.
             continue
         flag = get_flag_from_header(header_key, header_value)
         if self.command_name in DATA_TRANSFER_COMMANDS:
             if flag is None:
                 raise exception.GcloudStorageTranslationError(
                     'Header cannot be translated to a gcloud storage equivalent'
                     ' flag. Invalid header: {}:{}'.format(
                         header_key, header_value))
             else:
                 flags.append(flag)
         elif (self.command_name in PRECONDITONS_ONLY_SUPPORTED_COMMANDS
               and header_key in PRECONDITIONS_HEADERS):
             flags.append(flag)
         # We ignore the headers for all other cases, so does gsutil.
     return flags
Example #4
0
    def translate_to_gcloud_storage_if_requested(self):
        """Translates the gsutil command to gcloud storage equivalent.

    The translated commands get stored at
    self._translated_gcloud_storage_command.
    This command also translate the boto config, which gets stored as a dict
    at self._translated_env_variables
    
    Returns:
      True if the command was successfully translated, else False.
    """
        if self.command_name == 'version' or self.command_name == 'test':
            # Running any command in debug mode will lead to calling gsutil version
            # command. We don't want to translate the version command as this
            # should always reflect the version that gsutil is using.

            # We don't want to run any translation for the "test" command.
            return False
        use_gcloud_storage = config.getbool('GSUtil', 'use_gcloud_storage',
                                            False)
        try:
            hidden_shim_mode = HIDDEN_SHIM_MODE(
                config.get('GSUtil', 'hidden_shim_mode', 'none'))
        except ValueError:
            raise exception.CommandException(
                'Invalid option specified for'
                ' GSUtil:hidden_shim_mode config setting. Should be one of: {}'
                .format(' | '.join([x.value for x in HIDDEN_SHIM_MODE])))
        if use_gcloud_storage:
            try:
                top_level_flags, env_variables = self._translate_top_level_flags(
                )
                header_flags = self._translate_headers()

                flags_from_boto, env_vars_from_boto = self._translate_boto_config(
                )
                env_variables.update(env_vars_from_boto)

                gcloud_binary_path = _get_gcloud_binary_path()
                gcloud_storage_command = ([gcloud_binary_path] +
                                          self.get_gcloud_storage_args() +
                                          top_level_flags + header_flags +
                                          flags_from_boto)
                if hidden_shim_mode == HIDDEN_SHIM_MODE.DRY_RUN:
                    self._print_gcloud_storage_command_info(
                        gcloud_storage_command, env_variables, dry_run=True)
                elif not os.environ.get(
                        'CLOUDSDK_CORE_PASS_CREDENTIALS_TO_GSUTIL'):
                    raise exception.GcloudStorageTranslationError(
                        'Requested to use "gcloud storage" but gsutil is not using the'
                        ' same credentials as gcloud.'
                        ' You can make gsutil use the same credentials by running:\n'
                        '{} config set pass_credentials_to_gsutil True'.format(
                            gcloud_binary_path))
                else:
                    self._print_gcloud_storage_command_info(
                        gcloud_storage_command, env_variables)
                    self._translated_gcloud_storage_command = gcloud_storage_command
                    self._translated_env_variables = env_variables
                    return True
            except exception.GcloudStorageTranslationError as e:
                # Raise error if no_fallback mode has been requested. This mode
                # should only be used for debuggling and testing purposes.
                if hidden_shim_mode == HIDDEN_SHIM_MODE.NO_FALLBACK:
                    raise exception.CommandException(e)
                # For all other cases, we want to run gsutil.
                self.logger.error(
                    'Cannot translate gsutil command to gcloud storage.'
                    ' Going to run gsutil command. Error: %s', e)
        return False