Example #1
0
    def _watch_resource_completions(self, timeout):
        '''
        Watch and wait for resource completions.
        Returns lists of resources in various conditions for the calling
        function to handle.
        '''
        LOG.debug(
            'Starting to wait on: namespace=%s, resource type=%s, '
            'label_selector=(%s), timeout=%s',
            self.chart_wait.release_id.namespace, self.resource_type,
            self.label_selector, timeout)
        ready = {}
        modified = set()
        found_resources = False

        kwargs = {
            'namespace': self.chart_wait.release_id.namespace,
            'label_selector': self.label_selector,
            'timeout_seconds': timeout
        }

        resource_list = self.get_resources(**kwargs)
        for resource in resource_list.items:
            # Only include resources that should be included in wait ops
            if self.include_resource(resource):
                ready[resource.metadata.name] = self.handle_resource(resource)
        if not resource_list.items:
            if not self.required:
                msg = 'Skipping non-required wait, no %s resources found.'
                LOG.debug(msg, self.resource_type)
                return (False, modified, [], found_resources)
        else:
            found_resources = True
            if all(ready.values()):
                return (False, modified, [], found_resources)

        # Only watch new events.
        kwargs['resource_version'] = resource_list.metadata.resource_version

        w = watch.Watch()
        for event in w.stream(self.get_resources, **kwargs):
            event_type = event['type'].upper()
            resource = event['object']
            resource_name = resource.metadata.name
            resource_version = resource.metadata.resource_version

            # Skip resources that should be excluded from wait operations
            if not self.include_resource(resource):
                continue

            msg = (
                'Watch event: type=%s, name=%s, namespace=%s, '
                'resource_version=%s')
            LOG.debug(
                msg, event_type, resource_name,
                self.chart_wait.release_id.namespace, resource_version)

            if event_type in {'ADDED', 'MODIFIED'}:
                found_resources = True
                resource_ready = self.handle_resource(resource)
                ready[resource_name] = resource_ready

                if event_type == 'MODIFIED':
                    modified.add(resource_name)

            elif event_type == 'DELETED':
                LOG.debug('Resource %s: removed from tracking', resource_name)
                ready.pop(resource_name)

            elif event_type == 'ERROR':
                LOG.error(
                    'Resource %s: Got error event %s', resource_name,
                    event['object'].to_dict())
                raise k8s_exceptions.KubernetesErrorEventException(
                    'Got error event for resource: %s' % event['object'])

            else:
                LOG.error(
                    'Unrecognized event type (%s) for resource: %s',
                    event_type, event['object'])
                raise (
                    k8s_exceptions.
                    KubernetesUnknownStreamingEventTypeException(
                        'Got unknown event type (%s) for resource: %s' %
                        (event_type, event['object'])))

            if all(ready.values()):
                return (False, modified, [], found_resources)

        return (
            True, modified,
            [name for name, is_ready in ready.items()
             if not is_ready], found_resources)
Example #2
0
    def _watch_pod_completions(self, namespace, label_selector, timeout=100):
        '''
        Watch and wait for pod completions.
        Returns lists of pods in various conditions for the calling function
        to handle.
        '''
        LOG.debug(
            'Starting to wait on pods: namespace=%s, label_selector=(%s), '
            'timeout=%s', namespace, label_selector, timeout)
        ready_pods = {}
        modified_pods = set()
        w = watch.Watch()
        first_event = True
        found_events = False

        # Watch across specific namespace, or all
        kwargs = {
            'label_selector': label_selector,
            'timeout_seconds': timeout,
        }
        if namespace:
            func_to_call = self.client.list_namespaced_pod
            kwargs['namespace'] = namespace
        else:
            func_to_call = self.client.list_pod_for_all_namespaces

        for event in w.stream(func_to_call, **kwargs):
            if first_event:
                pod_list = func_to_call(**kwargs)
                for pod in pod_list.items:
                    LOG.debug('Setting up to wait for pod %s namespace=%s',
                              pod.metadata.name, pod.metadata.namespace)
                    ready_pods[pod.metadata.name] = False
                first_event = False

            event_type = event['type'].upper()
            pod_name = event['object'].metadata.name
            LOG.debug('Watch event for pod %s namespace=%s label_selector=%s',
                      pod_name, namespace, label_selector)

            if event_type in {'ADDED', 'MODIFIED'}:
                found_events = True
                status = event['object'].status
                pod_phase = status.phase

                pod_ready = True
                if (pod_phase == 'Succeeded'
                        or (pod_phase == 'Running' and self._get_pod_condition(
                            status.conditions, 'Ready') == 'True')):
                    LOG.debug('Pod %s is ready!', pod_name)
                else:
                    pod_ready = False
                    LOG.debug(
                        'Pod %s not ready: conditions:\n%s\n'
                        'container_statuses:\n%s', pod_name, status.conditions,
                        status.container_statuses)

                ready_pods[pod_name] = pod_ready

                if event_type == 'MODIFIED':
                    modified_pods.add(pod_name)

            elif event_type == 'DELETED':
                LOG.debug('Pod %s: removed from tracking', pod_name)
                ready_pods.pop(pod_name)

            elif event_type == 'ERROR':
                LOG.error('Pod %s: Got error event %s', pod_name,
                          event['object'].to_dict())
                raise exceptions.KubernetesErrorEventException(
                    'Got error event for pod: %s' % event['object'])

            else:
                LOG.error('Unrecognized event type (%s) for pod: %s',
                          event_type, event['object'])
                raise exceptions.KubernetesUnknownStreamingEventTypeException(
                    'Got unknown event type (%s) for pod: %s' %
                    (event_type, event['object']))

            if all(ready_pods.values()):
                return (False, modified_pods, [], found_events)

        # NOTE(mark-burnett): This path is reachable if there are no pods
        # (unlikely) or in the case of the watch timing out.
        return (not all(ready_pods.values()), modified_pods,
                [name for name, ready in ready_pods.items()
                 if not ready], found_events)
Example #3
0
    def wait_one_time(self, label_selector='', timeout=100):
        LOG.debug('Starting to wait: label_selector=%s, timeout=%s',
                  label_selector, timeout)
        ready_pods = {}
        modified_pods = set()
        w = watch.Watch()
        first_event = True
        for event in w.stream(self.client.list_pod_for_all_namespaces,
                              label_selector=label_selector,
                              timeout_seconds=timeout):
            if first_event:
                pod_list = self.client.list_pod_for_all_namespaces(
                    label_selector=label_selector, timeout_seconds=timeout)
                for pod in pod_list.items:
                    LOG.debug('Setting up to wait for pod %s',
                              pod.metadata.name)
                    ready_pods[pod.metadata.name] = False
                first_event = False

            event_type = event['type'].upper()
            pod_name = event['object'].metadata.name

            if event_type in {'ADDED', 'MODIFIED'}:
                status = event['object'].status
                is_ready = status.phase in READY_PHASES

                if is_ready:
                    LOG.debug('Pod %s (%s) is_ready=%s', pod_name, event_type,
                              is_ready)
                else:
                    container_statuses = status.container_statuses
                    conditions = status.conditions
                    LOG.debug(
                        'Pod %s (%s) is_ready=%s container_statuses=%s '
                        'conditions=%s', pod_name, event_type, is_ready,
                        container_statuses, conditions)

                ready_pods[pod_name] = is_ready

                if event_type == 'MODIFIED':
                    modified_pods.add(pod_name)

            elif event_type == 'DELETED':
                LOG.debug('Removing pod %s from tracking', pod_name)
                ready_pods.pop(pod_name)

            elif event_type == 'ERROR':
                LOG.error('Got error event for pod: %s',
                          event['object'].to_dict())
                raise exceptions.KubernetesErrorEventException(
                    'Got error event for pod: %s' % event['object'])

            else:
                LOG.error('Unrecognized event type (%s) for pod: %s',
                          event_type, event['object'])
                raise exceptions.KubernetesUnknownStreamingEventTypeException(
                    'Got unknown event type (%s) for pod: %s' %
                    (event_type, event['object']))

            if all(ready_pods.values()):
                return (False, modified_pods, [])

        # NOTE(mark-burnett): This path is reachable if there are no pods
        # (unlikely) or in the case of the watch timing out.
        return (not all(ready_pods.values()), modified_pods,
                [name for name, ready in ready_pods.items() if not ready])