Ejemplo n.º 1
0
    def test_get_undercloud_registry(self, mock_interfaces, mock_addresses):
        mock_interfaces.return_value = ['lo', 'eth0']
        self.assertEqual('localhost:8787',
                         image_uploader.get_undercloud_registry())

        mock_interfaces.return_value = ['lo', 'eth0', 'br-ctlplane']
        mock_addresses.return_value = {2: [{'addr': '192.0.2.0'}]}
        self.assertEqual('192.0.2.0:8787',
                         image_uploader.get_undercloud_registry())
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)" % parsed_args)

        if not parsed_args.yes:
            confirm = utils.prompt_user_for_confirmation(
                    message=_("Are you sure you want to delete this image "
                              "[y/N]? "),
                    logger=self.log)
            if not confirm:
                raise oscexc.CommandError("Action not confirmed, exiting.")

        lock = processlock.ProcessLock()
        manager = image_uploader.ImageUploadManager(lock=lock)
        uploader = manager.uploader('python')
        registry_url_arg = parsed_args.registry_url
        if registry_url_arg is None:
            registry_url_arg = image_uploader.get_undercloud_registry()
        url = uploader._image_to_url(registry_url_arg)
        session = uploader.authenticate(url, parsed_args.username,
                                        parsed_args.password)

        try:
            uploader.delete(parsed_args.image_to_delete, session=session)
        except OSError as e:
            self.log.error("Unable to remove due to permissions. "
                           "Please prefix command with sudo.")
            raise oscexc.CommandError(e)
 def get_parser(self, prog_name):
     parser = super(TripleOContainerImageDelete, self).get_parser(prog_name)
     parser.add_argument(
         "--registry-url",
         dest="registry_url",
         metavar='<registry url>',
         default=image_uploader.get_undercloud_registry(),
         help=_("URL of registry images are to be listed from in the "
                "form <fqdn>:<port>."))
     parser.add_argument(dest="image_to_delete",
                         metavar='<image to delete>',
                         help=_("Full URL of image to be deleted in the "
                                "form <fqdn>:<port>/path/to/image"))
     parser.add_argument("--username",
                         dest="username",
                         metavar='<username>',
                         help=_("Username for image registry."))
     parser.add_argument("--password",
                         dest="password",
                         metavar='<password>',
                         help=_("Password for image registry."))
     parser.add_argument('-y',
                         '--yes',
                         help=_('Skip yes/no prompt (assume yes).'),
                         default=False,
                         action="store_true")
     return parser
 def get_parser(self, prog_name):
     parser = super(TripleOContainerImagePush, self).get_parser(prog_name)
     parser.add_argument(
         "--local",
         dest="local",
         default=False,
         action="store_true",
         help=_("Use this flag if the container image is already on the "
                "current system and does not need to be pulled from a "
                "remote registry."))
     parser.add_argument("--registry-url",
                         dest="registry_url",
                         metavar='<registry url>',
                         default=image_uploader.get_undercloud_registry(),
                         help=_(
                             "URL of the destination registry in the form "
                             "<fqdn>:<port>."))
     parser.add_argument(
         "--append-tag",
         dest="append_tag",
         default='',
         help=_("Tag to append to the existing tag when pushing the "
                "container. "))
     parser.add_argument(
         "--username",
         dest="username",
         metavar='<username>',
         help=_("Username for the destination image registry."))
     parser.add_argument(
         "--password",
         dest="password",
         metavar='<password>',
         help=_("Password for the destination image registry."))
     parser.add_argument(
         "--dry-run",
         dest="dry_run",
         action="store_true",
         help=_("Perform a dry run upload. The upload action is not "
                "performed, but the authentication process is attempted."))
     parser.add_argument(
         "--multi-arch",
         dest="multi_arch",
         action="store_true",
         help=_("Enable multi arch support for the upload."))
     parser.add_argument(
         "--cleanup",
         dest="cleanup",
         action="store_true",
         default=False,
         help=_("Remove local copy of the image after uploading"))
     parser.add_argument(
         dest="image_to_push",
         metavar='<image to push>',
         help=_("Container image to upload. Should be in the form of "
                "<registry>/<namespace>/<name>:<tag>. If tag is "
                "not provided, then latest will be used."))
     return parser
Ejemplo n.º 5
0
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)" % parsed_args)

        cip = copy.deepcopy(kolla_builder.CONTAINER_IMAGE_PREPARE_PARAM)
        if parsed_args.push_destination:
            local_registry = image_uploader.get_undercloud_registry()
            for entry in cip:
                entry['push_destination'] = local_registry
        params = {'ContainerImagePrepare': cip}
        env_data = build_env_file(params, self.app.command_options)
        self.app.stdout.write(env_data)
        if parsed_args.output_env_file:
            with os.fdopen(
                    os.open(parsed_args.output_env_file,
                            os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0o666),
                    'w') as f:
                f.write(env_data)
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)" % parsed_args)

        lock = processlock.ProcessLock()
        manager = image_uploader.ImageUploadManager(lock=lock)
        uploader = manager.uploader('python')
        registry_url_arg = parsed_args.registry_url
        if registry_url_arg is None:
            registry_url_arg = image_uploader.get_undercloud_registry()
        url = uploader._image_to_url(registry_url_arg)
        session = uploader.authenticate(url, parsed_args.username,
                                        parsed_args.password)
        results = uploader.list(url.geturl(), session=session)
        cliff_results = []
        for r in results:
            cliff_results.append((r,))
        return (("Image Name",), cliff_results)
 def get_parser(self, prog_name):
     parser = super(TripleOContainerImageList, self).get_parser(prog_name)
     parser.add_argument(
         "--registry-url",
         dest="registry_url",
         metavar='<registry url>',
         default=image_uploader.get_undercloud_registry(),
         help=_("URL of registry images are to be listed from in the "
                "form <fqdn>:<port>."))
     parser.add_argument("--username",
                         dest="username",
                         metavar='<username>',
                         help=_("Username for image registry."))
     parser.add_argument("--password",
                         dest="password",
                         metavar='<password>',
                         help=_("Password for image registry."))
     return parser
Ejemplo n.º 8
0
def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
                             excludes=None,
                             includes=None,
                             service_filter=None,
                             pull_source=None,
                             push_destination=None,
                             mapping_args=None,
                             output_env_file=None,
                             output_images_file=None,
                             tag_from_label=None,
                             append_tag=None,
                             modify_role=None,
                             modify_vars=None,
                             modify_only_with_labels=None,
                             mirrors=None):
    """Perform container image preparation

    :param template_file: path to Jinja2 file containing all image entries
    :param excludes: list of image name substrings to use for exclude filter
    :param includes: list of image name substrings, at least one must match.
                     All excludes are ignored if includes is specified.
    :param service_filter: set of heat resource types for containerized
                           services to filter by. Disable by passing None.
    :param pull_source: DEPRECATED namespace for pulling during image uploads
    :param push_destination: namespace for pushing during image uploads. When
                             specified the image parameters will use this
                             namespace too.
    :param mapping_args: dict containing substitutions for template file. See
                         CONTAINER_IMAGES_DEFAULTS for expected keys.
    :param output_env_file: key to use for heat environment parameter data
    :param output_images_file: key to use for image upload data
    :param tag_from_label: string when set will trigger tag discovery on every
                           image
    :param append_tag: string to append to the tag for the destination
                              image
    :param modify_role: string of ansible role name to run during upload before
                        the push to destination
    :param modify_vars: dict of variables to pass to modify_role
    :param modify_only_with_labels: only modify the container images with the
                                    given labels
    :param mirrors: dict of registry netloc values to mirror urls
    :returns: dict with entries for the supplied output_env_file or
              output_images_file
    """

    if mapping_args is None:
        mapping_args = {}

    def ffunc(entry):
        imagename = entry.get('imagename', '')
        if service_filter is not None:
            # check the entry is for a service being deployed
            image_services = set(entry.get('services', []))
            if not image_services.intersection(service_filter):
                return None
        if includes:
            for p in includes:
                if re.search(p, imagename):
                    return entry
            return None
        if excludes:
            for p in excludes:
                if re.search(p, imagename):
                    return None
        return entry

    builder = KollaImageBuilder([template_file])
    result = builder.container_images_from_template(filter=ffunc,
                                                    **mapping_args)

    manager = image_uploader.ImageUploadManager(mirrors=mirrors)
    uploader = manager.uploader('python')
    images = [i.get('imagename', '') for i in result]

    if tag_from_label:
        image_version_tags = uploader.discover_image_tags(
            images, tag_from_label)
        for entry in result:
            imagename = entry.get('imagename', '')
            image_no_tag = imagename.rpartition(':')[0]
            if image_no_tag in image_version_tags:
                entry['imagename'] = '%s:%s' % (
                    image_no_tag, image_version_tags[image_no_tag])

    if modify_only_with_labels:
        images_with_labels = uploader.filter_images_with_labels(
            images, modify_only_with_labels)

    params = {}
    modify_append_tag = append_tag
    for entry in result:
        imagename = entry.get('imagename', '')
        append_tag = ''
        if modify_role and ((not modify_only_with_labels)
                            or imagename in images_with_labels):
            entry['modify_role'] = modify_role
            if modify_append_tag:
                entry['modify_append_tag'] = modify_append_tag
                append_tag = modify_append_tag
            if modify_vars:
                entry['modify_vars'] = modify_vars
        if pull_source:
            entry['pull_source'] = pull_source
        if push_destination:
            # substitute discovered registry if push_destination is set to true
            if isinstance(push_destination, bool):
                push_destination = image_uploader.get_undercloud_registry()

            entry['push_destination'] = push_destination
            # replace the host portion of the imagename with the
            # push_destination, since that is where they will be uploaded to
            image = imagename.partition('/')[2]
            imagename = '/'.join((push_destination, image))
        if 'params' in entry:
            for p in entry.pop('params'):
                params[p] = imagename + append_tag
        if 'services' in entry:
            del (entry['services'])

    params.update(detect_insecure_registries(params))

    return_data = {}
    if output_env_file:
        return_data[output_env_file] = params
    if output_images_file:
        return_data[output_images_file] = result
    return return_data
Ejemplo n.º 9
0
def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
                             excludes=None, includes=None, service_filter=None,
                             pull_source=None, push_destination=None,
                             mapping_args=None, output_env_file=None,
                             output_images_file=None, tag_from_label=None,
                             append_tag=None, modify_role=None,
                             modify_vars=None, modify_only_with_labels=None,
                             mirrors=None, registry_credentials=None):
    """Perform container image preparation

    :param template_file: path to Jinja2 file containing all image entries
    :param excludes: list of image name substrings to use for exclude filter
    :param includes: list of image name substrings, at least one must match.
                     All excludes are ignored if includes is specified.
    :param service_filter: set of heat resource types for containerized
                           services to filter by. Disable by passing None.
    :param pull_source: DEPRECATED namespace for pulling during image uploads
    :param push_destination: namespace for pushing during image uploads. When
                             specified the image parameters will use this
                             namespace too.
    :param mapping_args: dict containing substitutions for template file. See
                         CONTAINER_IMAGES_DEFAULTS for expected keys.
    :param output_env_file: key to use for heat environment parameter data
    :param output_images_file: key to use for image upload data
    :param tag_from_label: string when set will trigger tag discovery on every
                           image
    :param append_tag: string to append to the tag for the destination
                              image
    :param modify_role: string of ansible role name to run during upload before
                        the push to destination
    :param modify_vars: dict of variables to pass to modify_role
    :param modify_only_with_labels: only modify the container images with the
                                    given labels
    :param mirrors: dict of registry netloc values to mirror urls
    :param registry_credentials: dict of registry netloc values to
                                 authentication credentials for that registry.
                                 The value is a single-entry dict where the
                                 username is the key and the password is the
                                 value.
    :returns: dict with entries for the supplied output_env_file or
              output_images_file
    """

    if mapping_args is None:
        mapping_args = {}

    def ffunc(entry):
        imagename = entry.get('imagename', '')
        if service_filter is not None:
            # check the entry is for a service being deployed
            image_services = set(entry.get('services', []))
            if not image_services.intersection(service_filter):
                return None
        if includes:
            for p in includes:
                if re.search(p, imagename):
                    return entry
            return None
        if excludes:
            for p in excludes:
                if re.search(p, imagename):
                    return None
        return entry

    builder = KollaImageBuilder([template_file])
    result = builder.container_images_from_template(
        filter=ffunc, **mapping_args)

    manager = image_uploader.ImageUploadManager(
        mirrors=mirrors, registry_credentials=registry_credentials)
    uploader = manager.uploader('python')
    images = [i.get('imagename', '') for i in result]

    if tag_from_label:
        image_version_tags = uploader.discover_image_tags(
            images, tag_from_label)
        for entry in result:
            imagename = entry.get('imagename', '')
            image_no_tag = imagename.rpartition(':')[0]
            if image_no_tag in image_version_tags:
                entry['imagename'] = '%s:%s' % (
                    image_no_tag, image_version_tags[image_no_tag])

    if modify_only_with_labels:
        images_with_labels = uploader.filter_images_with_labels(
            images, modify_only_with_labels)

    params = {}
    modify_append_tag = append_tag
    for entry in result:
        imagename = entry.get('imagename', '')
        append_tag = ''
        if modify_role and (
                (not modify_only_with_labels) or
                imagename in images_with_labels):
            entry['modify_role'] = modify_role
            if modify_append_tag:
                entry['modify_append_tag'] = modify_append_tag
                append_tag = modify_append_tag
            if modify_vars:
                entry['modify_vars'] = modify_vars
        if pull_source:
            entry['pull_source'] = pull_source
        if push_destination:
            # substitute discovered registry if push_destination is set to true
            if isinstance(push_destination, bool):
                push_destination = image_uploader.get_undercloud_registry()

            entry['push_destination'] = push_destination
            # replace the host portion of the imagename with the
            # push_destination, since that is where they will be uploaded to
            image = imagename.partition('/')[2]
            imagename = '/'.join((push_destination, image))
        if 'params' in entry:
            for p in entry.pop('params'):
                params[p] = imagename + append_tag
        if 'services' in entry:
            del(entry['services'])

    params.update(
        detect_insecure_registries(params))

    return_data = {}
    if output_env_file:
        return_data[output_env_file] = params
    if output_images_file:
        return_data[output_images_file] = result
    return return_data
Ejemplo n.º 10
0
def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
                             template_dir=DEFAULT_TEMPLATE_DIR,
                             excludes=None,
                             includes=None,
                             service_filter=None,
                             pull_source=None,
                             push_destination=None,
                             mapping_args=None,
                             output_env_file=None,
                             output_images_file=None,
                             tag_from_label=None,
                             append_tag=None,
                             modify_role=None,
                             modify_vars=None,
                             modify_only_with_labels=None,
                             modify_only_with_source=None,
                             mirrors=None,
                             registry_credentials=None,
                             multi_arch=False,
                             lock=None):
    """Perform container image preparation

    :param template_file: path to Jinja2 file containing all image entries
    :param template_dir: path to Jinja2 files included in the main template
    :param excludes: list of image name substrings to use for exclude filter
    :param includes: list of image name substrings, at least one must match.
                     All excludes are ignored if includes is specified.
    :param service_filter: set of heat resource types for containerized
                           services to filter by. Disable by passing None.
    :param pull_source: DEPRECATED namespace for pulling during image uploads
    :param push_destination: namespace for pushing during image uploads. When
                             specified the image parameters will use this
                             namespace too.
    :param mapping_args: dict containing substitutions for template file. See
                         CONTAINER_IMAGES_DEFAULTS for expected keys.
    :param output_env_file: key to use for heat environment parameter data
    :param output_images_file: key to use for image upload data
    :param tag_from_label: string when set will trigger tag discovery on every
                           image
    :param append_tag: string to append to the tag for the destination
                              image
    :param modify_role: string of ansible role name to run during upload before
                        the push to destination
    :param modify_vars: dict of variables to pass to modify_role
    :param modify_only_with_labels: only modify the container images with the
                                    given labels
    :param modify_only_with_source: only modify the container images from a
                                    image_source in the tripleo-common service
                                    to container mapping (e.g. kolla/tripleo)
    :param mirrors: dict of registry netloc values to mirror urls
    :param registry_credentials: dict of registry netloc values to
                                 authentication credentials for that registry.
                                 The value is a single-entry dict where the
                                 username is the key and the password is the
                                 value.
    :param multi_arch: boolean whether to prepare every architecture of
                       each image

    :param lock: a locking object to use when handling uploads
    :returns: dict with entries for the supplied output_env_file or
              output_images_file
    """

    if mapping_args is None:
        mapping_args = {}

    if not lock:
        lock = threadinglock.ThreadingLock()

    def ffunc(entry):
        imagename = entry.get('imagename', '')
        if service_filter is not None:
            # check the entry is for a service being deployed
            image_services = set(entry.get('services', []))
            if not image_services.intersection(service_filter):
                return None
        if includes:
            for p in includes:
                if re.search(p, imagename):
                    return entry
            return None
        if excludes:
            for p in excludes:
                if re.search(p, imagename):
                    return None
        return entry

    builder = KollaImageBuilder([template_file], template_dir)
    result = builder.container_images_from_template(filter=ffunc,
                                                    **mapping_args)

    manager = image_uploader.ImageUploadManager(
        mirrors=mirrors,
        registry_credentials=registry_credentials,
        multi_arch=multi_arch,
        lock=lock)
    uploader = manager.uploader('python')
    images = [i.get('imagename', '') for i in result]
    # set a flag to record whether the default tag is used or not. the
    # logic here is that if the tag key is not already in mapping then it
    # wil be added during the template render, so default_tag is set to
    # True.
    default_tag = 'tag' not in mapping_args

    if tag_from_label:
        image_version_tags = uploader.discover_image_tags(
            images, tag_from_label, default_tag)
        for entry in result:
            imagename = entry.get('imagename', '')
            image_no_tag = imagename.rpartition(':')[0]
            if image_no_tag in image_version_tags:
                entry['imagename'] = '%s:%s' % (
                    image_no_tag, image_version_tags[image_no_tag])

    images_with_labels = []
    if modify_only_with_labels:
        images_with_labels = uploader.filter_images_with_labels(
            images, modify_only_with_labels)

    images_with_source = []
    if modify_only_with_source:
        images_with_source = [
            i.get('imagename') for i in result
            if i.get('image_source', '') in modify_only_with_source
        ]

    params = {}
    modify_append_tag = append_tag
    for entry in result:
        imagename = entry.get('imagename', '')
        append_tag = ''
        if modify_role and (
            (not modify_only_with_labels and not modify_only_with_source) or
            (imagename in images_with_labels
             or imagename in images_with_source)):
            entry['modify_role'] = modify_role
            if modify_append_tag:
                entry['modify_append_tag'] = modify_append_tag
                append_tag = modify_append_tag
            if modify_vars:
                entry['modify_vars'] = modify_vars
        if pull_source:
            entry['pull_source'] = pull_source
        if push_destination:
            # substitute discovered registry if push_destination is set to true
            if isinstance(push_destination, bool):
                push_destination = image_uploader.get_undercloud_registry()

            entry['push_destination'] = push_destination
            # replace the host portion of the imagename with the
            # push_destination, since that is where they will be uploaded to
            image = imagename.partition('/')[2]
            imagename = '/'.join((push_destination, image))
        if 'params' in entry:
            for p in entry.pop('params'):
                params[p] = imagename + append_tag
        if 'services' in entry:
            del (entry['services'])

    params.update(detect_insecure_registries(params, lock=lock))

    return_data = {}
    if output_env_file:
        return_data[output_env_file] = params
    if output_images_file:
        return_data[output_images_file] = result
    return return_data
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)" % parsed_args)

        lock = processlock.ProcessLock()
        manager = image_uploader.ImageUploadManager(lock=lock)
        uploader = manager.uploader('python')

        source_image = parsed_args.image_to_push

        if parsed_args.local or source_image.startswith('containers-storage:'):
            storage = 'containers-storage:'
            if not source_image.startswith(storage):
                source_image = storage + source_image.replace('docker://', '')
            elif not parsed_args.local:
                self.log.warning('Assuming local container based on provided '
                                 'container path. (e.g. starts with '
                                 'containers-storage:)')
            source_url = parse.urlparse(source_image)
            image_name = source_url.geturl()
            image_source = None
            if parsed_args.source_username or parsed_args.source_password:
                self.log.warning('Source credentials ignored for local images')
        else:
            storage = 'docker://'
            if not source_image.startswith(storage):
                source_image = storage + source_image
            source_url = parse.urlparse(source_image)
            image_source = source_url.netloc
            image_name = source_url.path[1:]
            if len(image_name.split('/')) != 2:
                raise exceptions.DownloadError('Invalid container. Provided '
                                               'container image should be '
                                               '<registry>/<namespace>/<name>:'
                                               '<tag>')
            if parsed_args.source_username or parsed_args.source_password:
                if not parsed_args.source_username:
                    self.log.warning('Skipping authentication - missing source'
                                     ' username')
                elif not parsed_args.source_password:
                    self.log.warning('Skipping authentication - missing source'
                                     ' password')
                else:
                    uploader.authenticate(source_url,
                                          parsed_args.source_username,
                                          parsed_args.source_password)

        registry_url_arg = parsed_args.registry_url
        if registry_url_arg is None:
            registry_url_arg = image_uploader.get_undercloud_registry()
        if not registry_url_arg.startswith('docker://'):
            registry_url = 'docker://%s' % registry_url_arg
        else:
            registry_url = registry_url_arg
        reg_url = parse.urlparse(registry_url)

        uploader.authenticate(reg_url,
                              parsed_args.username,
                              parsed_args.password)

        task = image_uploader.UploadTask(
                image_name=image_name,
                pull_source=image_source,
                push_destination=registry_url_arg,
                append_tag=parsed_args.append_tag,
                modify_role=None,
                modify_vars=None,
                dry_run=parsed_args.dry_run,
                cleanup=parsed_args.cleanup,
                multi_arch=parsed_args.multi_arch)
        try:
            uploader.add_upload_task(task)
            uploader.run_tasks()
        except OSError as e:
            self.log.error("Unable to upload due to permissions. "
                           "Please prefix command with sudo.")
            raise oscexc.CommandError(e)