def _copy_files_from_image(image, src_path, dest_path): """ Copy a file from the container image into the given destination path. The file may be a directory. :param str image: the pull specification of the container image. :param str src_path: the full path within the container image to copy from. :param str dest_path: the full path on the local host to copy into. """ # Check that image is pullable podman_pull(image) # One way to copy a file from the image is to create a container from its filesystem # so the contents can be read. To create a container, podman always requires that a # command for the container is set. In this method, however, the command is not needed # because the container is never started, only created. Use a dummy command to satisfy # podman. container_command = 'unused' container_id = run_cmd( ['podman', 'create', image, container_command], exc_msg=f'Failed to create a container for {image}', ).strip() try: run_cmd( ['podman', 'cp', f'{container_id}:{src_path}', dest_path], exc_msg= f'Failed to copy the contents of {container_id}:{src_path} into {dest_path}', ) finally: try: run_cmd( ['podman', 'rm', container_id], exc_msg= f'Failed to remove the container {container_id} for image {image}', ) except IIBError as e: # Failure to remove the temporary container shouldn't cause the IIB request to fail. log.exception(e)
def handle_regenerate_bundle_request(from_bundle_image, organization, request_id): """ Coordinate the work needed to regenerate the operator bundle image. :param str from_bundle_image: the pull specification of the bundle image to be regenerated. :param str organization: the name of the organization the bundle should be regenerated for. :param int request_id: the ID of the IIB build request :raises IIBError: if the regenerate bundle image build fails. """ _cleanup() set_request_state(request_id, 'in_progress', 'Resolving from_bundle_image') from_bundle_image_resolved = _get_resolved_image(from_bundle_image) arches = _get_image_arches(from_bundle_image_resolved) if not arches: raise IIBError( f'No arches were found in the resolved from_bundle_image {from_bundle_image_resolved}' ) arches_str = ', '.join(sorted(arches)) log.debug( 'Set to regenerate the bundle image for the following arches: %s', arches_str) payload = { 'from_bundle_image_resolved': from_bundle_image_resolved, 'state': 'in_progress', 'state_reason': f'Regenerating the bundle image for the following arches: {arches_str}', } exc_msg = 'Failed setting the resolved "from_bundle_image" on the request' update_request(request_id, payload, exc_msg=exc_msg) # Pull the from_bundle_image to ensure steps later on don't fail due to registry timeouts podman_pull(from_bundle_image_resolved) with tempfile.TemporaryDirectory(prefix='iib-') as temp_dir: manifests_path = os.path.join(temp_dir, 'manifests') _copy_files_from_image(from_bundle_image_resolved, '/manifests', manifests_path) metadata_path = os.path.join(temp_dir, 'metadata') _copy_files_from_image(from_bundle_image_resolved, '/metadata', metadata_path) labels = _adjust_operator_bundle(manifests_path, metadata_path, organization) with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as dockerfile: dockerfile.write( textwrap.dedent(f"""\ FROM {from_bundle_image_resolved} COPY ./manifests /manifests COPY ./metadata /metadata """)) for name, value in labels.items(): dockerfile.write(f'LABEL {name}={value}\n') for arch in sorted(arches): _build_image(temp_dir, 'Dockerfile', request_id, arch) _push_image(request_id, arch) set_request_state(request_id, 'in_progress', 'Creating the manifest list') output_pull_spec = _create_and_push_manifest_list(request_id, arches) conf = get_worker_config() if conf['iib_index_image_output_registry']: old_output_pull_spec = output_pull_spec output_pull_spec = output_pull_spec.replace( conf['iib_registry'], conf['iib_index_image_output_registry'], 1) log.info( 'Changed the bundle_image pull specification from %s to %s', old_output_pull_spec, output_pull_spec, ) payload = { 'arches': list(arches), 'bundle_image': output_pull_spec, 'state': 'complete', 'state_reason': 'The request completed successfully', } update_request(request_id, payload, exc_msg='Failed setting the bundle image on the request')
def test_podman_pull(mock_run_cmd): image = 'some-image:latest' utils.podman_pull(image) mock_run_cmd.assert_called_once_with(['podman', 'pull', image], exc_msg=mock.ANY)