Esempio n. 1
0
    def testProgressBarLabel(self):
        pb = console_io.ProgressBar('Test Action', total_ticks=15)
        pb.Start()
        self.AssertErrContains('3= Test Action =4\n')

        self.ClearErr()
        pb = console_io.ProgressBar('Test Action', total_ticks=14)
        pb.Start()
        self.AssertErrContains('3= Test Ac... =4\n')
Esempio n. 2
0
def _StartMinikubeCluster(cluster_name, vm_driver, debug=False):
  """Starts a minikube cluster."""
  # pylint: disable=broad-except
  try:
    if not _IsMinikubeClusterUp(cluster_name):
      cmd = [
          _FindMinikube(),
          'start',
          '-p',
          cluster_name,
          '--keep-context',
          '--interactive=false',
          '--delete-on-failure',
          '--install-addons=false',
          '--output=json',
      ]
      if vm_driver:
        cmd.append('--vm-driver=' + vm_driver)
        if vm_driver == 'docker':
          cmd.append('--container-runtime=docker')
      if debug:
        cmd.extend(['--alsologtostderr', '-v8'])

      start_msg = "Starting development environment '%s' ..." % cluster_name

      with console_io.ProgressBar(start_msg) as progress_bar:
        for json_obj in run_subprocess.StreamOutputJson(
            cmd, event_timeout_sec=90, show_stderr=debug):
          if debug:
            print('minikube', json_obj)

          _HandleMinikubeStatusEvent(progress_bar, json_obj)
  except Exception as e:
    six.reraise(MinikubeStartError, e, sys.exc_info()[2])
Esempio n. 3
0
    def _UpdateWithProgressBar(self,
                               components,
                               action,
                               action_func,
                               first=False,
                               last=False):
        """Performs an update on a component while using a progress bar.

    Args:
      components: [schemas.Component], The components that are going to be acted
        on.
      action: str, The action that is printed for this update.
      action_func: func, The function to call to actually do the update.  It
        takes a single argument which is the component id.
      first: bool, True if this is the first stacked ProgressBar group.
      last: bool, True if this is the last stacked ProgressBar group.
    """
        for index, component in enumerate(components):
            label = '{action}: {name}'.format(
                action=action, name=component.details.display_name)
            with console_io.ProgressBar(
                    label=label,
                    stream=log.status,
                    first=first,
                    last=last and index == len(components) - 1) as pb:
                action_func(component.id, progress_callback=pb.SetProgress)
            first = False
Esempio n. 4
0
 def testNoOp(self):
     properties.VALUES.core.interactive_ux_style.Set(
         properties.VALUES.core.InteractiveUXStyles.OFF.name)
     pb = console_io.ProgressBar('Test Action', total_ticks=40)
     pb.Start()
     pb.Finish()
     self.AssertErrEquals('')
Esempio n. 5
0
 def testStub(self):
     properties.VALUES.core.interactive_ux_style.Set(
         properties.VALUES.core.InteractiveUXStyles.TESTING.name)
     pb = console_io.ProgressBar('Test Action', total_ticks=40)
     pb.Start()
     pb.Finish()
     self.AssertErrEquals(
         '{"ux": "PROGRESS_BAR", "message": "Test Action"}\n')
Esempio n. 6
0
 def Start(self, total_files):
     self._progress_bar = console_io.ProgressBar(
         'Uploading {0} file(s)'.format(total_files))
     (self.read_progress,
      self.write_progress) = (console_io.SplitProgressBar(
          self._progress_bar.SetProgress, [1, 6]))
     self._workspace.SetPostCallback(self._UpdateWriteProgress)
     self.total_files = total_files
     self._progress_bar.Start()
Esempio n. 7
0
 def testProgressBarScreenReader(self):
     pb = console_io.ProgressBar('Test Action', screen_reader=True)
     pb.Start()
     self.AssertErrEquals('Test Action\n')
     pb.SetProgress(0.02)
     self.AssertErrEquals('Test Action\n')
     pb.SetProgress(0.33)
     self.AssertErrEquals('Test Action\n33%\n')
     pb.Finish()
     self.AssertErrEquals('Test Action\n33%\n100%\n')
Esempio n. 8
0
 def testDefault(self):
     with console_io.ProgressBar('', total_ticks=10):
         callbacks = console_io.SplitProgressBar(None, [.1, .4, .5])
         self.assertEqual(3, len(callbacks))
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
         callbacks[0](1)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
         callbacks[1](1)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
         callbacks[2](1)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
  def _Update(self, restrict):
    """Update() helper method. Returns the number of changed help doc files."""
    with file_utils.TemporaryDirectory() as temp_dir:
      pb = console_io.ProgressBar(label='Generating Help Document Files')
      with TimeIt('Creating walker'):
        walker = self._generator(
            self._cli, temp_dir, pb.SetProgress, restrict=restrict)
      start = time.time()
      pb.Start()
      walker.Walk(hidden=True)
      pb.Finish()
      elapsed_time = time.time() - start
      log.info('Generating Help Document Files took {}'.format(elapsed_time))

      diff = HelpAccumulator(restrict=restrict)
      with TimeIt('Diffing'):
        DirDiff(self._directory, temp_dir, diff)
      ops = collections.defaultdict(list)

      changes = 0
      with TimeIt('Getting diffs'):
        for op, path in sorted(diff.GetChanges()):
          changes += 1
          if not self._test or changes < TEST_CHANGES_DISPLAY_MAX:
            log.status.Print('{0} {1}'.format(op, path))
          ops[op].append(path)

      if self._test:
        if changes:
          if changes >= TEST_CHANGES_DISPLAY_MAX:
            log.status.Print('...')
          log.status.Print('{0} help text {1} changed'.format(
              changes, text.Pluralize(changes, 'file')))
        return changes

      with TimeIt('Updating destination files'):
        for op in ('add', 'edit', 'delete'):
          for path in ops[op]:
            dest_path = os.path.join(self._directory, path)
            if op in ('add', 'edit'):
              if op == 'add':
                subdir = os.path.dirname(dest_path)
                if subdir:
                  file_utils.MakeDir(subdir)
              temp_path = os.path.join(temp_dir, path)
              shutil.copyfile(temp_path, dest_path)
            elif op == 'delete':
              try:
                os.remove(dest_path)
              except OSError:
                pass

      return changes
Esempio n. 10
0
  def _AddSourceDirToWorkspace(self, workspace, src_name, target_root):
    """Add files in the given directory to a workspace.

    Args:
      workspace: (source.Workspace) The workspace to add files to.
      src_name: (string) A directory to snapshot.
      target_root: (string) Root directory of the target tree in the snapshot.
    Returns:
      ([dict], int, int) A 3-tuple containing an array of source contexts,
      the number of files added to the workspace, and the total size of the
      files added.
    """

    src_path = os.path.abspath(src_name)
    source_contexts = []
    # Add context for any external repos.
    try:
      for s in contexts.CalculateExtendedSourceContexts(src_path):
        if s not in source_contexts:
          source_contexts.append(s)
    except contexts.GenerateSourceContextError:
      # We don't care if there's no external source context. We can even
      # snapshot a bunch of local files if necessary.
      pass

    # TODO(danielsb) Once "wsync snapshot" is available, use that instead of
    # explicitly modifying the workspace as we do here.

    paths = [os.path.relpath(os.path.join(basedir, f), src_path)
             for basedir, _, files in os.walk(src_path) for f in files]
    total_files = len(paths)
    progress_bar = console_io.ProgressBar(
        'Uploading {0} files'.format(total_files))
    (read_progress, write_progress) = console_io.ProgressBar.SplitProgressBar(
        progress_bar.SetProgress, [1, 6])
    def UpdateProgress(action_count):
      write_progress((1.0 * action_count) / total_files)
    workspace.SetPostCallback(UpdateProgress)
    progress_bar.Start()

    total_size = 0
    file_count = 0
    contents = None
    for path in paths:
      with open(os.path.join(src_path, path), 'r') as f:
        contents = f.read()
      if contents:
        total_size += len(contents)
        file_count += 1
        read_progress((1.0 * file_count) / total_files)
        workspace.WriteFile(os.path.join(target_root, path), contents)
    return (source_contexts, total_files, total_size)
Esempio n. 11
0
    def _AddSourceJarToWorkspace(self, workspace, src_name, target_root):
        """Add files in the given source jar to a workspace.

    Args:
      workspace: (source.Workspace) The workspace to add files to.
      src_name: (string) A directory tree or source jar to snapshot.
      target_root: (string) Root directory of the target tree in the snapshot.
    Returns:
      ([dict], int, int) A 3-tuple containing an array of source contexts,
      the number of files added to the workspace, and the total size of the
      files added.
    """

        source_contexts = []
        jar_file = None
        try:
            jar_file = zipfile.ZipFile(src_name, 'r')
            paths = [
                zi.filename for zi in jar_file.infolist()
                if zi.filename.endswith('.java')
            ]

            total_files = len(paths)
            progress_bar = console_io.ProgressBar(
                'Uploading {0} files'.format(total_files))
            (read_progress,
             write_progress) = console_io.ProgressBar.SplitProgressBar(
                 progress_bar.SetProgress, [1, 6])

            def UpdateProgress(action_count):
                write_progress((1.0 * action_count) / total_files)

            workspace.SetPostCallback(UpdateProgress)
            progress_bar.Start()

            total_size = 0
            file_count = 0
            for path in paths:
                contents = jar_file.read(path)
                if contents:
                    total_size += len(contents)
                    file_count += 1
                    read_progress((1.0 * file_count) / total_files)
                    workspace.WriteFile(os.path.join(target_root, path),
                                        contents)
        finally:
            if jar_file:
                jar_file.close()
        return (source_contexts, total_files, total_size)
Esempio n. 12
0
    def _UpdateWithProgressBar(self, components, action, action_func):
        """Performs an update on a component while using a progress bar.

    Args:
      components: [schemas.Component], The components that are going to be acted
        on.
      action: str, The action that is printed for this update.
      action_func: func, The function to call to actually do the update.  It
        takes a single argument which is the component id.
    """
        for component in components:
            label = '{action}: {name}'.format(
                action=action, name=component.details.display_name)
            with console_io.ProgressBar(label=label, stream=log.status) as pb:
                action_func(component.id, progress_callback=pb.SetProgress)
Esempio n. 13
0
    def testProgressBarAsciiArtStack(self):
        actions = ['Uninstalling', 'Downloading', 'Installing']
        for index, action in enumerate(actions):
            pb = console_io.ProgressBar(action,
                                        total_ticks=40,
                                        first=index == 0,
                                        last=index == len(actions) - 1)
            pb.Start()
            pb.Finish()

        self.AssertErrEquals('#========================================#\n'
                             '#= Uninstalling                         =#\n'
                             '#========================================#\n'
                             '#= Downloading                          =#\n'
                             '#========================================#\n'
                             '#= Installing                           =#\n'
                             '#========================================#\n')
Esempio n. 14
0
    def DownloadModule(self, module, version, output_dir):
        """Downloads the given version of the module.

    Args:
      module: str, The module to download.
      version: str, The version of the module to download.
      output_dir: str, The directory to download the module to.
    """
        rpcserver = self._GetRpcServer()
        downloader = module_downloader.ModuleDownloader(
            rpcserver, self.project, module, version)
        (full_version, file_lines) = downloader.GetFileList()
        with console_io.ProgressBar(label='Downloading [{0}] files...'.format(
                len(file_lines)),
                                    stream=log.status) as pb:
            downloader.Download(full_version, file_lines, output_dir,
                                pb.SetProgress)
Esempio n. 15
0
    def testProgressBarAsciiArtStackNonInteractive(self):
        """Don't make double lines when the char set is ascii."""
        self._interactive_mock.return_value = False
        actions = ['Uninstalling', 'Downloading', 'Installing']
        for index, action in enumerate(actions):
            pb = console_io.ProgressBar(action,
                                        total_ticks=40,
                                        first=index == 0,
                                        last=index == len(actions) - 1)
            pb.Start()
            pb.Finish()

        self.AssertErrEquals('#========================================#\n'
                             '#= Uninstalling                         =#\n'
                             '#========================================#\n'
                             '#= Downloading                          =#\n'
                             '#========================================#\n'
                             '#= Installing                           =#\n'
                             '#========================================#\n')
Esempio n. 16
0
    def testProgressBarAsciiArtSingle(self):
        pb = console_io.ProgressBar('Test Action', total_ticks=40)
        self.AssertErrNotContains('|')
        pb.Start()
        self.AssertErrContains('#========================================#\n'
                               '#= Test Action                          =#\n'
                               '#')

        pb.SetProgress(.25)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#==========')

        pb.SetProgress(.15)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#==========')

        pb.SetProgress(.26)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#==========')

        pb.SetProgress(.49)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#===================')

        pb.SetProgress(.50)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#====================')

        pb.SetProgress(1)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#========================================#\n')

        # Should just stay at 100%.
        pb.SetProgress(2)
        self.AssertErrEquals('#========================================#\n'
                             '#= Test Action                          =#\n'
                             '#========================================#\n')
Esempio n. 17
0
 def testSplit(self):
     with console_io.ProgressBar('', total_ticks=10) as pb:
         callbacks = console_io.SplitProgressBar(pb.SetProgress,
                                                 [.1, .4, .5])
         self.assertEqual(3, len(callbacks))
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
         callbacks[0](.5)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5')
         callbacks[0](1)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5=')
         callbacks[1](.5)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5===')
         callbacks[1](1)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5=====')
         callbacks[2](.5)
         self.AssertErrEquals('1==========2\n' '3=        =4\n' '5=======')
         callbacks[2](1)
         self.AssertErrEquals('1==========2\n'
                              '3=        =4\n'
                              '5==========6\n')
Esempio n. 18
0
    def testProgressBarStackNonInteractive(self):
        """Don't redraw when non-interactive."""
        self._interactive_mock.return_value = False
        actions = ['Uninstalling', 'Downloading', 'Installing']
        for index, action in enumerate(actions):
            pb = console_io.ProgressBar(action,
                                        total_ticks=40,
                                        first=index == 0,
                                        last=index == len(actions) - 1)
            pb.Start()
            pb.Finish()

        self.AssertErrEquals('1========================================2\n'
                             '3= Uninstalling                         =4\n'
                             '5========================================6\n'
                             '1========================================2\n'
                             '3= Downloading                          =4\n'
                             '5========================================6\n'
                             '1========================================2\n'
                             '3= Installing                           =4\n'
                             '5========================================6\n')
Esempio n. 19
0
    def Update(self,
               update_seed=None,
               allow_no_backup=False,
               throw_if_unattended=False):
        """Performs an update of the given components.

    If no components are provided, it will attempt to update everything you have
    installed.

    Args:
      update_seed: list of str, A list of component ids to update.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.
      throw_if_unattended: bool, True to throw an exception on prompts when
        not running in interactive mode.

    Returns:
      bool, True if the update succeeded (or there was nothing to do, False if
      if was cancelled by the user.

    Raises:
      InvalidComponentError: If any of the given component ids do not exist.
    """
        md5dict1 = self._HashRcfiles(_SHELL_RCFILES)
        self._EnsureNotDisabled()

        old_release_notes = release_notes.GetReleaseNotes(self.__sdk_root)

        try:
            install_state, diff = self._GetStateAndDiff(
                command_path='components.update')
        except snapshots.IncompatibleSchemaVersionError as e:
            return self._ReinstallOnError(e)

        if update_seed:
            invalid_seeds = diff.InvalidUpdateSeeds(update_seed)
            if invalid_seeds:
                if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
                    # We are doing a reinstall.  Ignore any components that no longer
                    # exist.
                    update_seed = set(update_seed) - invalid_seeds
                else:
                    ignored = set(_IGNORED_MISSING_COMPONENTS)
                    deprecated = invalid_seeds & ignored
                    for item in deprecated:
                        log.warning('Component [%s] no longer exists.', item)
                        additional_msg = _IGNORED_MISSING_COMPONENTS.get(item)
                        if additional_msg:
                            log.warning(additional_msg)
                    invalid_seeds -= ignored
                    if invalid_seeds:
                        raise InvalidComponentError(
                            'The following components are unknown [{invalid_seeds}]'
                            .format(invalid_seeds=', '.join(invalid_seeds)))
                    update_seed = set(update_seed) - deprecated
        else:
            update_seed = diff.current.components.keys()

        to_remove = diff.ToRemove(update_seed)
        to_install = diff.ToInstall(update_seed)

        self.__Write(log.status)
        if not to_remove and not to_install:
            self.__Write(log.status, 'All components are up to date.')
            with install_state.LastUpdateCheck() as update_check:
                update_check.SetFromSnapshot(
                    diff.latest,
                    force=True,
                    platform_filter=self.__platform_filter)
            return True

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        self._PrintPendingAction(
            diff.DetailsForCurrent(to_remove - to_install), 'removed')
        self._PrintPendingAction(diff.DetailsForLatest(to_remove & to_install),
                                 'updated')
        self._PrintPendingAction(diff.DetailsForLatest(to_install - to_remove),
                                 'installed')
        self.__Write(log.status)

        if diff.latest.sdk_definition.release_notes_url:
            self.__Write(
                log.status,
                'For the latest full release notes, please visit:\n  {0}'.
                format(diff.latest.sdk_definition.release_notes_url))

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(
                message=message, throw_if_unattended=throw_if_unattended):
            return False

        components_to_install = diff.DetailsForLatest(to_install)
        components_to_remove = diff.DetailsForCurrent(to_remove)

        for c in components_to_install:
            metrics.Installs(c.id, c.version.version_string)

        if disable_backup:
            with execution_utils.UninterruptibleSection(stream=log.status):
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall)
                self._UpdateWithProgressBar(
                    components_to_install, 'Installing',
                    self._InstallFunction(install_state, diff))
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self.__Write(log.status)
            self._UpdateWithProgressBar(components_to_remove, 'Uninstalling',
                                        staging_state.Uninstall)
            self._UpdateWithProgressBar(
                components_to_install, 'Installing',
                self._InstallFunction(staging_state, diff))
            self.__Write(log.status)
            self.__Write(log.status,
                         'Creating backup and activating new installation...')
            install_state.ReplaceWith(staging_state)

        with install_state.LastUpdateCheck() as update_check:
            update_check.SetFromSnapshot(
                diff.latest,
                force=True,
                platform_filter=self.__platform_filter)
        md5dict2 = self._HashRcfiles(_SHELL_RCFILES)
        if md5dict1 != md5dict2:
            self.__Write(
                log.status,
                '\nStart a new shell for the changes to take effect.\n')
        self.__Write(log.status, '\nUpdate done!\n')

        if self.__warn:
            bad_commands = self.FindAllOldToolsOnPath()
            if bad_commands and not os.environ.get(
                    'CLOUDSDK_REINSTALL_COMPONENTS'):
                log.warning("""\
There are older versions of Google Cloud Platform tools on your system PATH.
Please remove the following to avoid accidentally invoking these old tools:

{0}

""".format('\n'.join(bad_commands)))

        new_release_notes = release_notes.GetReleaseNotes(self.__sdk_root)
        changed_entries = release_notes.ChangesBetween(old_release_notes,
                                                       new_release_notes)
        if changed_entries:
            log.status.Print(
                'The following release notes are new in this upgrade. '
                'Please read carefully for information about new '
                'features, breaking changes, and bugs fixed:\n')
            log.status.Print('\n\n'.join(changed_entries))

        return True
Esempio n. 20
0
 def testProgressBarContextManager(self):
     with console_io.ProgressBar('Test Action', total_ticks=15):
         pass
     self.AssertErrEquals('1===============2\n'
                          '3= Test Action =4\n'
                          '5===============6\n')
Esempio n. 21
0
    def _Update(self, restrict):
        """Update() helper method. Returns the number of changed help text files."""
        with file_utils.TemporaryDirectory() as temp_dir:
            pb = console_io.ProgressBar(label='Generating Help Docs')
            walker = walker_util.HelpTextGenerator(self._cli,
                                                   temp_dir,
                                                   pb.SetProgress,
                                                   restrict=restrict)
            pb.Start()
            walker.Walk(hidden=True)
            pb.Finish()
            diff = HelpTextAccumulator(restrict=restrict)
            DirDiff(self._help_dir, temp_dir, diff)
            if diff.invalid_file_count:
                # Bail out early on invalid content errors. These must be corrected
                # before proceeding.
                raise HelpTextUpdateError(
                    '{0} help text {1} with invalid content must be fixed.'.
                    format(diff.invalid_file_count,
                           text.Pluralize(diff.invalid_file_count, 'file')))

            ops = {}
            for op in ['add', 'delete', 'edit']:
                ops[op] = []

            changes = 0
            for op, path in sorted(diff.GetChanges()):
                changes += 1
                if not self._test or changes < TEST_CHANGES_DISPLAY_MAX:
                    log.status.Print('{0} {1}'.format(op, path))
                ops[op].append(path)

            if self._test:
                if changes:
                    if changes >= TEST_CHANGES_DISPLAY_MAX:
                        log.status.Print('...')
                    log.status.Print('{0} help test {1} changed'.format(
                        changes, text.Pluralize(changes, 'file')))
                return changes

            op = 'add'
            if ops[op]:
                for path in ops[op]:
                    dest_path = os.path.join(self._help_dir, path)
                    subdir = os.path.dirname(dest_path)
                    if subdir:
                        file_utils.MakeDir(subdir)
                    temp_path = os.path.join(temp_dir, path)
                    shutil.copyfile(temp_path, dest_path)

            op = 'edit'
            if ops[op]:
                for path in ops[op]:
                    dest_path = os.path.join(self._help_dir, path)
                    temp_path = os.path.join(temp_dir, path)
                    shutil.copyfile(temp_path, dest_path)

            op = 'delete'
            if ops[op]:
                for path in ops[op]:
                    dest_path = os.path.join(self._help_dir, path)
                    try:
                        os.remove(dest_path)
                    except OSError:
                        pass

            return changes
Esempio n. 22
0
    def Update(self,
               update_seed=None,
               allow_no_backup=False,
               throw_if_unattended=False):
        """Performs an update of the given components.

    If no components are provided, it will attempt to update everything you have
    installed.

    Args:
      update_seed: list of str, A list of component ids to update.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.
      throw_if_unattended: bool, True to throw an exception on prompts when
        not running in interactive mode.

    Returns:
      bool, True if the update succeeded (or there was nothing to do, False if
      if was cancelled by the user.

    Raises:
      InvalidComponentError: If any of the given component ids do not exist.
    """
        md5dict1 = self._HashRcfiles(_SHELL_RCFILES)
        self._EnsureNotDisabled()

        try:
            install_state, diff = self._GetStateAndDiff(
                command_path='components.update')
        except snapshots.IncompatibleSchemaVersionError as e:
            return self._ReinstallOnError(e)

        original_update_seed = update_seed
        if update_seed:
            invalid_seeds = diff.InvalidUpdateSeeds(update_seed)
            if invalid_seeds:
                if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
                    # We are doing a reinstall.  Ignore any components that no longer
                    # exist.
                    update_seed = set(update_seed) - invalid_seeds
                else:
                    ignored = set(_IGNORED_MISSING_COMPONENTS)
                    deprecated = invalid_seeds & ignored
                    for item in deprecated:
                        log.warning('Component [%s] no longer exists.', item)
                        additional_msg = _IGNORED_MISSING_COMPONENTS.get(item)
                        if additional_msg:
                            log.warning(additional_msg)
                    invalid_seeds -= ignored
                    if invalid_seeds:
                        raise InvalidComponentError(
                            'The following components are unknown [{invalid_seeds}]'
                            .format(invalid_seeds=', '.join(invalid_seeds)))
                    update_seed = set(update_seed) - deprecated
        else:
            update_seed = diff.current.components.keys()

        to_remove = diff.ToRemove(update_seed)
        to_install = diff.ToInstall(update_seed)

        self.__Write(log.status)
        if not to_remove and not to_install:
            self.__Write(log.status, 'All components are up to date.')
            with install_state.LastUpdateCheck() as update_check:
                update_check.SetFromSnapshot(
                    diff.latest,
                    force=True,
                    platform_filter=self.__platform_filter)
            return True

        current_os = platforms.OperatingSystem.Current()
        if (current_os is platforms.OperatingSystem.WINDOWS and
                file_utils.IsDirAncestorOf(self.__sdk_root, sys.executable)):
            # On Windows, you can't use a Python installed within a directory to move
            # that directory, which means that with a bundled Python, updates will
            # fail. To get around this, we copy the Python interpreter to a temporary
            # directory and run it there.
            # There's no issue that the `.py` files themselves are inside the install
            # directory, because the Python interpreter loads them into memory and
            # closes them immediately.
            RestartCommand(python=_CopyPython(), block=False)
            sys.exit(0)

        # If explicitly listing components, you are probably installing and not
        # doing a full udpate, change the message to be more clear.
        if original_update_seed:
            latest_msg = 'Installing components from version: '
        else:
            latest_msg = 'You will be upgraded to version: '
        self._PrintVersions(diff, latest_msg=latest_msg)

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        self._PrintPendingAction(
            diff.DetailsForCurrent(to_remove - to_install), 'removed')
        self._PrintPendingAction(diff.DetailsForLatest(to_remove & to_install),
                                 'updated')
        self._PrintPendingAction(diff.DetailsForLatest(to_install - to_remove),
                                 'installed')
        self.__Write(log.status)

        release_notes.PrintReleaseNotesDiff(
            diff.latest.sdk_definition.release_notes_url,
            config.INSTALLATION_CONFIG.version, diff.latest.version)

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(
                message=message, throw_if_unattended=throw_if_unattended):
            return False

        components_to_install = diff.DetailsForLatest(to_install)
        components_to_remove = diff.DetailsForCurrent(to_remove)

        for c in components_to_install:
            metrics.Installs(c.id, c.version.version_string)

        if disable_backup:
            with execution_utils.UninterruptibleSection(stream=log.status):
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall,
                                            first=True,
                                            last=not components_to_install)
                self._UpdateWithProgressBar(components_to_install,
                                            'Installing',
                                            self._InstallFunction(
                                                install_state, diff),
                                            first=not components_to_remove,
                                            last=True)
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status,
                                        last=False) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self._UpdateWithProgressBar(components_to_remove,
                                        'Uninstalling',
                                        staging_state.Uninstall,
                                        first=False,
                                        last=False)
            self._UpdateWithProgressBar(components_to_install,
                                        'Installing',
                                        self._InstallFunction(
                                            staging_state, diff),
                                        first=False,
                                        last=False)
            with console_io.ProgressBar(
                    label='Creating backup and activating new installation',
                    stream=log.status,
                    first=False) as pb:
                install_state.ReplaceWith(staging_state, pb.SetProgress)

        with install_state.LastUpdateCheck() as update_check:
            update_check.SetFromSnapshot(
                diff.latest,
                force=True,
                platform_filter=self.__platform_filter)
        md5dict2 = self._HashRcfiles(_SHELL_RCFILES)
        if md5dict1 != md5dict2:
            self.__Write(
                log.status,
                '\nStart a new shell for the changes to take effect.\n')
        self.__Write(log.status, '\nUpdate done!\n')

        if self.__warn:
            bad_commands = self.FindAllOldToolsOnPath()
            if bad_commands and not os.environ.get(
                    'CLOUDSDK_REINSTALL_COMPONENTS'):
                log.warning("""\
There are older versions of Google Cloud Platform tools on your system PATH.
Please remove the following to avoid accidentally invoking these old tools:

{0}

""".format('\n'.join(bad_commands)))
        return True
Esempio n. 23
0
    def Remove(self, ids, allow_no_backup=False):
        """Uninstalls the given components.

    Args:
      ids: list of str, The component ids to uninstall.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.

    Raises:
      InvalidComponentError: If any of the given component ids are not
        installed or cannot be removed.
    """
        self._EnsureNotDisabled()
        if not ids:
            return

        install_state = self._GetInstallState()
        snapshot = install_state.Snapshot()
        id_set = set(ids)
        not_installed = id_set - set(snapshot.components.keys())
        if not_installed:
            raise InvalidComponentError(
                'The following components are not currently installed [{components}]'
                .format(components=', '.join(not_installed)))

        required_components = set(
            c_id for c_id, component in snapshot.components.iteritems()
            if c_id in id_set and component.is_required)
        if required_components:
            raise InvalidComponentError(
                ('The following components are required and cannot be removed '
                 '[{components}]').format(
                     components=', '.join(required_components)))

        to_remove = snapshot.ConsumerClosureForComponents(ids)
        if not to_remove:
            self.__Write(log.status, 'No components to remove.\n')
            return

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        components_to_remove = sorted(snapshot.ComponentsFromIds(to_remove),
                                      key=lambda c: c.details.display_name)
        self._PrintPendingAction(components_to_remove, 'removed')
        self.__Write(log.status)

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(message):
            return

        if disable_backup:
            with execution_utils.UninterruptibleSection(stream=log.status):
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall)
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self.__Write(log.status)
            self._UpdateWithProgressBar(components_to_remove, 'Uninstalling',
                                        staging_state.Uninstall)
            self.__Write(log.status)
            self.__Write(log.status,
                         'Creating backup and activating new installation...')
            install_state.ReplaceWith(staging_state)

        self.__Write(log.status, '\nUninstall done!\n')
Esempio n. 24
0
    def _DoFreshInstall(self, message, no_update, download_url):
        """Do a reinstall of what we have based on a fresh download of the SDK.

    Args:
      message: str, A message to show to the user before the re-installation.
      no_update: bool, True to show the message and tell the user they must
        re-download manually.
      download_url: The URL the Cloud SDK can be downloaded from.

    Returns:
      bool, True if the update succeeded, False if it was cancelled.
    """
        self._EnsureNotDisabled()
        if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
            # We are already reinstalling but got here somehow.  Something is very
            # wrong and we want to avoid the infinite loop.
            self._RaiseReinstallationFailedError()

        # Print out an arbitrary message that we wanted to show users for this
        # update.
        if message:
            self.__Write(log.status, msg=message, word_wrap=True)

        # We can decide that for some reason we just never want to update past this
        # version of the schema.
        if no_update:
            return False

        answer = console_io.PromptContinue(
            message=
            '\nThe component manager must perform a self update before you '
            'can continue.  It and all components will be updated to their '
            'latest versions.')
        if not answer:
            return False

        self._ShouldDoFastUpdate(allow_no_backup=False,
                                 fast_mode_impossible=True)
        install_state = self._GetInstallState()

        try:
            with console_io.ProgressBar(
                    label='Downloading and extracting updated components',
                    stream=log.status) as pb:
                staging_state = install_state.CreateStagingFromDownload(
                    download_url, progress_callback=pb.SetProgress)
        except local_state.Error:
            log.error('An updated Cloud SDK failed to download')
            log.debug('Handling re-installation error', exc_info=True)
            self._RaiseReinstallationFailedError()

        # shell out to install script
        installed_component_ids = sorted(
            install_state.InstalledComponents().keys())
        env = dict(os.environ)
        env['CLOUDSDK_REINSTALL_COMPONENTS'] = ','.join(
            installed_component_ids)
        installer_path = os.path.join(staging_state.sdk_root, 'bin',
                                      'bootstrapping', 'install.py')
        p = subprocess.Popen([sys.executable, '-S', installer_path], env=env)
        ret_val = p.wait()
        if ret_val:
            self._RaiseReinstallationFailedError()

        self.__Write(log.status,
                     'Creating backup and activating new installation...')
        install_state.ReplaceWith(staging_state)

        self.__Write(log.status, '\nComponents updated!\n')
        return True