summaryrefslogtreecommitdiff
path: root/glanceclient
diff options
context:
space:
mode:
authorCindy Pallares <cindy.pallaresq@gmail.com>2014-08-08 10:06:25 -0500
committerCindy Pallares <cindy.pallaresq@gmail.com>2014-08-12 05:30:59 -0500
commit1dfce5301c5d7cd456c98629a007917120637c8a (patch)
tree8c3382570b566929acd3ed91cc023b26a679203d /glanceclient
parent558ebf7bb75a600e7461e2dd3c360b01f8823aca (diff)
downloadpython-glanceclient-1dfce5301c5d7cd456c98629a007917120637c8a.tar.gz
Remove deprecated commands from shell
Remove all deprecated commands from the shell since they are no longer used and to keep the command line menu from looking cluttered. Closes-bug: #1314218 Change-Id: I66e82872988e3835e4f290f48dfc80538271426c
Diffstat (limited to 'glanceclient')
-rw-r--r--glanceclient/shell.py79
-rw-r--r--glanceclient/v1/legacy_shell.py515
-rw-r--r--glanceclient/v1/shell.py12
3 files changed, 3 insertions, 603 deletions
diff --git a/glanceclient/shell.py b/glanceclient/shell.py
index c066f53..f55375c 100644
--- a/glanceclient/shell.py
+++ b/glanceclient/shell.py
@@ -27,7 +27,6 @@ import os
from os.path import expanduser
import sys
-import netaddr
import six.moves.urllib.parse as urlparse
import glanceclient
@@ -134,11 +133,6 @@ class OpenStackImagesShell(object):
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-I',
- dest='os_username',
- help='DEPRECATED! Use --os-username.')
-
parser.add_argument('--os-password',
default=utils.env('OS_PASSWORD'),
help='Defaults to env[OS_PASSWORD].')
@@ -146,11 +140,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_password',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-K',
- dest='os_password',
- help='DEPRECATED! Use --os-password.')
-
parser.add_argument('--os-tenant-id',
default=utils.env('OS_TENANT_ID'),
help='Defaults to env[OS_TENANT_ID].')
@@ -165,11 +154,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_tenant_name',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-T',
- dest='os_tenant_name',
- help='DEPRECATED! Use --os-tenant-name.')
-
parser.add_argument('--os-auth-url',
default=utils.env('OS_AUTH_URL'),
help='Defaults to env[OS_AUTH_URL].')
@@ -177,11 +161,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_auth_url',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-N',
- dest='os_auth_url',
- help='DEPRECATED! Use --os-auth-url.')
-
parser.add_argument('--os-region-name',
default=utils.env('OS_REGION_NAME'),
help='Defaults to env[OS_REGION_NAME].')
@@ -189,11 +168,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_region_name',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-R',
- dest='os_region_name',
- help='DEPRECATED! Use --os-region-name.')
-
parser.add_argument('--os-auth-token',
default=utils.env('OS_AUTH_TOKEN'),
help='Defaults to env[OS_AUTH_TOKEN].')
@@ -201,11 +175,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_auth_token',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-A', '--auth_token',
- dest='os_auth_token',
- help='DEPRECATED! Use --os-auth-token.')
-
parser.add_argument('--os-service-type',
default=utils.env('OS_SERVICE_TYPE'),
help='Defaults to env[OS_SERVICE_TYPE].')
@@ -271,36 +240,6 @@ class OpenStackImagesShell(object):
help='Prevent select actions from requesting '
'user confirmation.')
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('--dry-run',
- default=False,
- action='store_true',
- help='DEPRECATED! Only used for deprecated '
- 'legacy commands.')
-
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('--ssl',
- dest='use_ssl',
- default=False,
- action='store_true',
- help='DEPRECATED! Send a fully-formed endpoint '
- 'using --os-image-url instead.')
-
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-H', '--host',
- metavar='ADDRESS',
- help='DEPRECATED! Send a fully-formed endpoint '
- 'using --os-image-url instead.')
-
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-p', '--port',
- dest='port',
- metavar='PORT',
- type=int,
- default=9292,
- help='DEPRECATED! Send a fully-formed endpoint '
- 'using --os-image-url instead.')
-
parser.add_argument('--os-image-url',
default=utils.env('OS_IMAGE_URL'),
help='Defaults to env[OS_IMAGE_URL].')
@@ -308,11 +247,6 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_image_url',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-U', '--url',
- dest='os_image_url',
- help='DEPRECATED! Use --os-image-url.')
-
parser.add_argument('--os-image-api-version',
default=utils.env('OS_IMAGE_API_VERSION',
default='1'),
@@ -321,12 +255,7 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_image_api_version',
help=argparse.SUPPRESS)
- #NOTE(bcwaldon): DEPRECATED
- parser.add_argument('-S', '--os_auth_strategy',
- help='DEPRECATED! This option is '
- 'completely ignored.')
-
- # FIXME(bobt): this method should come from python-keystoneclient
+ # FIXME(bobt): this method should come from python-keystoneclient
self._append_global_identity_args(parser)
return parser
@@ -374,12 +303,6 @@ class OpenStackImagesShell(object):
"""
if args.os_image_url:
return args.os_image_url
- elif args.host:
- # Check if it is legal ipv6 address, if so, need wrap it with '[]'
- if netaddr.valid_ipv6(args.host):
- args.host = '[%s]' % args.host
- scheme = 'https' if args.use_ssl else 'http'
- return '%s://%s:%s/' % (scheme, args.host, args.port)
else:
return None
diff --git a/glanceclient/v1/legacy_shell.py b/glanceclient/v1/legacy_shell.py
deleted file mode 100644
index 02f1ea3..0000000
--- a/glanceclient/v1/legacy_shell.py
+++ /dev/null
@@ -1,515 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""
-DEPRECATED functions that implement the same command line interface as the
-legacy glance client.
-"""
-
-from __future__ import print_function
-
-import argparse
-import sys
-
-from six.moves.urllib import parse
-
-from glanceclient.common import utils
-from glanceclient.openstack.common import strutils
-
-
-SUCCESS = 0
-FAILURE = 1
-
-
-def get_image_fields_from_args(args):
- """
- Validate the set of arguments passed as field name/value pairs
- and return them as a mapping.
- """
- fields = {}
- for arg in args:
- pieces = arg.strip(',').split('=')
- if len(pieces) != 2:
- msg = ("Arguments should be in the form of field=value. "
- "You specified %s." % arg)
- raise RuntimeError(msg)
- fields[pieces[0]] = pieces[1]
-
- return fields
-
-
-def get_image_filters_from_args(args):
- """Build a dictionary of query filters based on the supplied args."""
- try:
- fields = get_image_fields_from_args(args)
- except RuntimeError as e:
- print(e)
- return FAILURE
-
- SUPPORTED_FILTERS = ['name', 'disk_format', 'container_format', 'status',
- 'min_ram', 'min_disk', 'size_min', 'size_max',
- 'changes-since']
- filters = {}
- for (key, value) in fields.items():
- if key not in SUPPORTED_FILTERS:
- key = 'property-%s' % (key,)
- filters[key] = value
-
- return filters
-
-
-def print_image_formatted(client, image):
- """
- Formatted print of image metadata.
-
- :param client: The Glance client object
- :param image: The image metadata
- """
- uri_parts = parse.urlparse(client.http_client.endpoint)
- if uri_parts.port:
- hostbase = "%s:%s" % (uri_parts.hostname, uri_parts.port)
- else:
- hostbase = uri_parts.hostname
- print("URI: %s://%s/v1/images/%s" % (uri_parts.scheme, hostbase, image.id))
- print("Id: %s" % image.id)
- print("Public: " + (image.is_public and "Yes" or "No"))
- print("Protected: " + (image.protected and "Yes" or "No"))
- print("Name: %s" % getattr(image, 'name', ''))
- print("Status: %s" % image.status)
- print("Size: %d" % int(image.size))
- print("Disk format: %s" % getattr(image, 'disk_format', ''))
- print("Container format: %s" % getattr(image, 'container_format', ''))
- print("Minimum Ram Required (MB): %s" % image.min_ram)
- print("Minimum Disk Required (GB): %s" % image.min_disk)
- if hasattr(image, 'owner'):
- print("Owner: %s" % image.owner)
- if len(image.properties) > 0:
- for k, v in image.properties.items():
- print("Property '%s': %s" % (k, v))
- print("Created at: %s" % image.created_at)
- if hasattr(image, 'deleted_at'):
- print("Deleted at: %s" % image.deleted_at)
- if hasattr(image, 'updated_at'):
- print("Updated at: %s" % image.updated_at)
-
-
-@utils.arg('--silent-upload', action="store_true",
- help="DEPRECATED! Animations are always off.")
-@utils.arg('fields', default=[], nargs='*', help=argparse.SUPPRESS)
-def do_add(gc, args):
- """DEPRECATED! Use image-create instead."""
- try:
- fields = get_image_fields_from_args(args.fields)
- except RuntimeError as e:
- print(e)
- return FAILURE
-
- image_meta = {
- 'is_public': strutils.bool_from_string(
- fields.pop('is_public', 'False')),
- 'protected': strutils.bool_from_string(
- fields.pop('protected', 'False')),
- 'min_disk': fields.pop('min_disk', 0),
- 'min_ram': fields.pop('min_ram', 0),
- }
-
- #NOTE(bcwaldon): Use certain properties only if they are explicitly set
- optional = ['id', 'name', 'disk_format', 'container_format']
- for field in optional:
- if field in fields:
- image_meta[field] = fields.pop(field)
-
- # Strip any args that are not supported
- unsupported_fields = ['status', 'size']
- for field in unsupported_fields:
- if field in fields.keys():
- print('Found non-settable field %s. Removing.' % field)
- fields.pop(field)
-
- # We need either a location or image data/stream to add...
- image_data = None
- if 'location' in fields.keys():
- image_meta['location'] = fields.pop('location')
- if 'checksum' in fields.keys():
- image_meta['checksum'] = fields.pop('checksum')
- elif 'copy_from' in fields.keys():
- image_meta['copy_from'] = fields.pop('copy_from')
- else:
- # Grab the image data stream from stdin or redirect,
- # otherwise error out
- image_data = sys.stdin
-
- image_meta['data'] = image_data
-
- # allow owner to be set when image is created
- if 'owner' in fields.keys():
- image_meta['owner'] = fields.pop('owner')
-
- # Add custom attributes, which are all the arguments remaining
- image_meta['properties'] = fields
-
- if not args.dry_run:
- image = gc.images.create(**image_meta)
- print("Added new image with ID: %s" % image.id)
- if args.verbose:
- print("Returned the following metadata for the new image:")
- for k, v in sorted(image.to_dict().items()):
- print(" %(k)30s => %(v)s" % {'k': k, 'v': v})
- else:
- print("Dry run. We would have done the following:")
-
- def _dump(dict):
- for k, v in sorted(dict.items()):
- print(" %(k)30s => %(v)s" % {'k': k, 'v': v})
-
- print("Add new image with metadata:")
- _dump(image_meta)
-
- return SUCCESS
-
-
-@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
-@utils.arg('fields', default=[], nargs='*', help=argparse.SUPPRESS)
-def do_update(gc, args):
- """DEPRECATED! Use image-update instead."""
- try:
- fields = get_image_fields_from_args(args.fields)
- except RuntimeError as e:
- print(e)
- return FAILURE
-
- image_meta = {}
-
- # Strip any args that are not supported
- nonmodifiable_fields = ['created_at', 'deleted_at', 'deleted',
- 'updated_at', 'size', 'status']
- for field in nonmodifiable_fields:
- if field in fields.keys():
- print('Found non-modifiable field %s. Removing.' % field)
- fields.pop(field)
-
- base_image_fields = ['disk_format', 'container_format', 'name',
- 'min_disk', 'min_ram', 'location', 'owner',
- 'copy_from']
- for field in base_image_fields:
- fvalue = fields.pop(field, None)
- if fvalue is not None:
- image_meta[field] = fvalue
-
- # Have to handle "boolean" values specially...
- if 'is_public' in fields:
- image_meta['is_public'] = strutils.\
- bool_from_string(fields.pop('is_public'))
- if 'protected' in fields:
- image_meta['protected'] = strutils.\
- bool_from_string(fields.pop('protected'))
-
- # Add custom attributes, which are all the arguments remaining
- image_meta['properties'] = fields
-
- if not args.dry_run:
- image = gc.images.update(args.id, **image_meta)
- print("Updated image %s" % args.id)
-
- if args.verbose:
- print("Updated image metadata for image %s:" % args.id)
- print_image_formatted(gc, image)
- else:
- def _dump(dict):
- for k, v in sorted(dict.items()):
- print(" %(k)30s => %(v)s" % {'k': k, 'v': v})
-
- print("Dry run. We would have done the following:")
- print("Update existing image with metadata:")
- _dump(image_meta)
-
- return SUCCESS
-
-
-@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
-def do_delete(gc, args):
- """DEPRECATED! Use image-delete instead."""
- if not (args.force or
- user_confirm("Delete image %s?" % args.id, default=False)):
- print('Not deleting image %s' % args.id)
- return FAILURE
-
- gc.images.get(args.id).delete()
-
-
-@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
-def do_show(gc, args):
- """DEPRECATED! Use image-show instead."""
- image = gc.images.get(args.id)
- print_image_formatted(gc, image)
- return SUCCESS
-
-
-def _get_images(gc, args):
- parameters = {
- 'filters': get_image_filters_from_args(args.filters),
- 'page_size': args.limit,
- }
-
- optional_kwargs = ['marker', 'sort_key', 'sort_dir']
- for kwarg in optional_kwargs:
- value = getattr(args, kwarg, None)
- if value is not None:
- parameters[kwarg] = value
-
- return gc.images.list(**parameters)
-
-
-@utils.arg('--limit', dest="limit", metavar="LIMIT", default=10,
- type=int, help="Page size for image metadata requests.")
-@utils.arg('--marker', dest="marker", metavar="MARKER",
- default=None, help="Image index after which to begin pagination.")
-@utils.arg('--sort_key', dest="sort_key", metavar="KEY",
- help="Sort results by this image attribute.")
-@utils.arg('--sort_dir', dest="sort_dir", metavar="[desc|asc]",
- help="Sort results in this direction.")
-@utils.arg('filters', default=[], nargs='*', help=argparse.SUPPRESS)
-def do_index(gc, args):
- """DEPRECATED! Use image-list instead."""
- images = _get_images(gc, args)
-
- if not images:
- return SUCCESS
-
- pretty_table = PrettyTable()
- pretty_table.add_column(36, label="ID")
- pretty_table.add_column(30, label="Name")
- pretty_table.add_column(20, label="Disk Format")
- pretty_table.add_column(20, label="Container Format")
- pretty_table.add_column(14, label="Size", just="r")
-
- print(pretty_table.make_header())
-
- for image in images:
- print(pretty_table.make_row(image.id,
- image.name,
- image.disk_format,
- image.container_format,
- image.size))
-
-
-@utils.arg('--limit', dest="limit", metavar="LIMIT", default=10,
- type=int, help="Page size for image metadata requests.")
-@utils.arg('--marker', dest="marker", metavar="MARKER",
- default=None, help="Image index after which to begin pagination.")
-@utils.arg('--sort_key', dest="sort_key", metavar="KEY",
- help="Sort results by this image attribute.")
-@utils.arg('--sort_dir', dest="sort_dir", metavar="[desc|asc]",
- help="Sort results in this direction.")
-@utils.arg('filters', default='', nargs='*', help=argparse.SUPPRESS)
-def do_details(gc, args):
- """DEPRECATED! Use image-list instead."""
- images = _get_images(gc, args)
- for i, image in enumerate(images):
- if i == 0:
- print("=" * 80)
- print_image_formatted(gc, image)
- print("=" * 80)
-
-
-def do_clear(gc, args):
- """DEPRECATED!"""
- if not (args.force or
- user_confirm("Delete all images?", default=False)):
- print('Not deleting any images')
- return FAILURE
-
- images = gc.images.list()
- for image in images:
- if args.verbose:
- print('Deleting image %s "%s" ...' % (image.id, image.name),
- end=' ')
- try:
- image.delete()
- if args.verbose:
- print('done')
- except Exception as e:
- print('Failed to delete image %s' % image.id)
- print(e)
- return FAILURE
- return SUCCESS
-
-
-@utils.arg('image_id', help='Image ID to filters members with.')
-def do_image_members(gc, args):
- """DEPRECATED! Use member-list instead."""
- members = gc.image_members.list(image=args.image_id)
- sharers = 0
- # Output the list of members
- for memb in members:
- can_share = ''
- if memb.can_share:
- can_share = ' *'
- sharers += 1
- print("%s%s" % (memb.member_id, can_share))
-
- # Emit a footnote
- if sharers > 0:
- print("\n(*: Can share image)")
-
-
-@utils.arg('--can-share', default=False, action="store_true",
- help="Allow member to further share image.")
-@utils.arg('member_id',
- help='ID of member (typically tenant) to grant access.')
-def do_member_images(gc, args):
- """DEPRECATED! Use member-list instead."""
- members = gc.image_members.list(member=args.member_id)
-
- if not len(members):
- print("No images shared with member %s" % args.member_id)
- return SUCCESS
-
- sharers = 0
- # Output the list of images
- for memb in members:
- can_share = ''
- if memb.can_share:
- can_share = ' *'
- sharers += 1
- print("%s%s" % (memb.image_id, can_share))
-
- # Emit a footnote
- if sharers > 0:
- print("\n(*: Can share image)")
-
-
-@utils.arg('--can-share', default=False, action="store_true",
- help="Allow member to further share image.")
-@utils.arg('image_id', help='ID of image to describe.')
-@utils.arg('member_id',
- help='ID of member (typically tenant) to grant access.')
-def do_members_replace(gc, args):
- """DEPRECATED!"""
- if not args.dry_run:
- for member in gc.image_members.list(image=args.image_id):
- gc.image_members.delete(args.image_id, member.member_id)
- gc.image_members.create(args.image_id, args.member_id, args.can_share)
- else:
- print("Dry run. We would have done the following:")
- print('Replace members of image %s with "%s"'
- % (args.image_id, args.member_id))
- if args.can_share:
- print("New member would have been able to further share image.")
-
-
-@utils.arg('--can-share', default=False, action="store_true",
- help="Allow member to further share image.")
-@utils.arg('image_id', help='ID of image to describe.')
-@utils.arg('member_id',
- help='ID of member (typically tenant) to grant access.')
-def do_member_add(gc, args):
- """DEPRECATED! Use member-create instead."""
- if not args.dry_run:
- gc.image_members.create(args.image_id, args.member_id, args.can_share)
- else:
- print("Dry run. We would have done the following:")
- print('Add "%s" to membership of image %s' %
- (args.member_id, args.image_id))
- if args.can_share:
- print("New member would have been able to further share image.")
-
-
-def user_confirm(prompt, default=False):
- """
- Yes/No question dialog with user.
-
- :param prompt: question/statement to present to user (string)
- :param default: boolean value to return if empty string
- is received as response to prompt
-
- """
- if default:
- prompt_default = "[Y/n]"
- else:
- prompt_default = "[y/N]"
-
- # for bug 884116, don't issue the prompt if stdin isn't a tty
- if not (hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()):
- return default
-
- answer = raw_input("%s %s " % (prompt, prompt_default))
-
- if answer == "":
- return default
- else:
- return answer.lower() in ("yes", "y")
-
-
-class PrettyTable(object):
- """Creates an ASCII art table
-
- Example:
-
- ID Name Size Hits
- --- ----------------- ------------ -----
- 122 image 22 0
- """
- def __init__(self):
- self.columns = []
-
- def add_column(self, width, label="", just='l'):
- """Add a column to the table
-
- :param width: number of characters wide the column should be
- :param label: column heading
- :param just: justification for the column, 'l' for left,
- 'r' for right
- """
- self.columns.append((width, label, just))
-
- def make_header(self):
- label_parts = []
- break_parts = []
- for width, label, _ in self.columns:
- # NOTE(sirp): headers are always left justified
- label_part = self._clip_and_justify(label, width, 'l')
- label_parts.append(label_part)
-
- break_part = '-' * width
- break_parts.append(break_part)
-
- label_line = ' '.join(label_parts)
- break_line = ' '.join(break_parts)
- return '\n'.join([label_line, break_line])
-
- def make_row(self, *args):
- row = args
- row_parts = []
- for data, (width, _, just) in zip(row, self.columns):
- row_part = self._clip_and_justify(data, width, just)
- row_parts.append(row_part)
-
- row_line = ' '.join(row_parts)
- return row_line
-
- @staticmethod
- def _clip_and_justify(data, width, just):
- # clip field to column width
- clipped_data = str(data)[:width]
-
- if just == 'r':
- # right justify
- justified = clipped_data.rjust(width)
- else:
- # left justify
- justified = clipped_data.ljust(width)
-
- return justified
diff --git a/glanceclient/v1/shell.py b/glanceclient/v1/shell.py
index 10c12c1..7c5d289 100644
--- a/glanceclient/v1/shell.py
+++ b/glanceclient/v1/shell.py
@@ -26,9 +26,6 @@ from glanceclient import exc
from glanceclient.openstack.common import strutils
import glanceclient.v1.images
-#NOTE(bcwaldon): import deprecated cli functions
-from glanceclient.v1.legacy_shell import *
-
CONTAINER_FORMATS = 'Acceptable formats: ami, ari, aki, bare, and ovf.'
DISK_FORMATS = ('Acceptable formats: ami, ari, aki, vhd, vmdk, raw, '
'qcow2, vdi, and iso.')
@@ -213,7 +210,7 @@ def do_image_create(gc, args):
# Filter out None values
fields = dict(filter(lambda x: x[1] is not None, vars(args).items()))
- fields['is_public'] = fields.get('is_public') or fields.pop('public')
+ fields['is_public'] = fields.get('is_public')
if 'is_protected' in fields:
fields['protected'] = fields.pop('is_protected')
@@ -386,9 +383,4 @@ def do_member_create(gc, args):
def do_member_delete(gc, args):
"""Remove a shared image from a tenant."""
image_id = utils.find_resource(gc.images, args.image).id
- if not args.dry_run:
- gc.image_members.delete(image_id, args.tenant_id)
- else:
- print("Dry run. We would have done the following:")
- print('Remove "%s" from the member list of image '
- '"%s"' % (args.tenant_id, args.image))
+ gc.image_members.delete(image_id, args.tenant_id)