Ejemplo n.º 1
0
    def testDiscoverImages(self):
        """Test _DiscoverSignedImages."""
        paygen = self._GetPaygenBuildInstance()

        uri_base = 'gs://crt/foo-channel/foo-board/1.2.3'

        uri_basic = os.path.join(
            uri_base,
            'chromeos_1.2.3_foo-board_recovery_foo-channel_mp-v3.bin')
        uri_premp = os.path.join(
            uri_base,
            'chromeos_1.2.3_foo-board_recovery_foo-channel_premp.bin')

        self.mockUriList.return_value = [uri_basic, uri_premp]

        # Run the test.
        result = paygen._DiscoverSignedImages(self.target_build)

        # See if we got the results we expect.
        base_image_params = {
            'channel': 'foo-channel',
            'board': 'foo-board',
            'version': '1.2.3',
            'bucket': 'crt'
        }
        expected_basic = gspaths.Image(key='mp-v3',
                                       uri=uri_basic,
                                       **base_image_params)
        expected_premp = gspaths.Image(key='premp',
                                       uri=uri_premp,
                                       **base_image_params)
        expected_result = [expected_basic, expected_premp]

        self.assertEqual(result, expected_result)
Ejemplo n.º 2
0
    def setUp(self):
        self.old_image = gspaths.Image(
            channel='dev-channel',
            board='x86-alex',
            version='1620.0.0',
            key='mp-v3',
            uri=('gs://chromeos-releases-test/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_recovery_dev-channel_mp-v3.bin'))

        self.old_base_image = gspaths.Image(
            channel='dev-channel',
            board='x86-alex',
            version='1620.0.0',
            key='mp-v3',
            image_type='base',
            uri=('gs://chromeos-releases-test/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_base_dev-channel_mp-v3.bin'))

        self.new_image = gspaths.Image(
            channel='dev-channel',
            board='x86-alex',
            version='4171.0.0',
            key='mp-v3',
            uri=('gs://chromeos-releases-test/dev-channel/x86-alex/4171.0.0/'
                 'chromeos_4171.0.0_x86-alex_recovery_dev-channel_mp-v3.bin'))

        self.old_test_image = gspaths.UnsignedImageArchive(
            channel='dev-channel',
            board='x86-alex',
            version='1620.0.0',
            uri=('gs://chromeos-releases-test/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_recovery_dev-channel_test.bin'))

        self.new_test_image = gspaths.Image(
            channel='dev-channel',
            board='x86-alex',
            version='4171.0.0',
            uri=('gs://chromeos-releases-test/dev-channel/x86-alex/4171.0.0/'
                 'chromeos_4171.0.0_x86-alex_recovery_dev-channel_test.bin'))

        self.full_payload = gspaths.Payload(tgt_image=self.old_base_image,
                                            src_image=None,
                                            uri='gs://full_old_foo/boo')

        self.delta_payload = gspaths.Payload(tgt_image=self.new_image,
                                             src_image=self.old_image,
                                             uri='gs://delta_new_old/boo')

        self.full_test_payload = gspaths.Payload(
            tgt_image=self.old_test_image,
            src_image=None,
            uri='gs://full_old_foo/boo-test')

        self.delta_test_payload = gspaths.Payload(
            tgt_image=self.new_test_image,
            src_image=self.old_test_image,
            uri='gs://delta_new_old/boo-test')
Ejemplo n.º 3
0
  def testParseImageUri(self):
    npo_version = self._IncrementVersion(self.version)
    npo_channel = 'nplusone-channel'

    basic_dict = dict(self.image_attrs)
    npo_dict = dict(self.image_attrs,
                    bucket=self._CHROMEOS_RELEASES_BUCKET,
                    image_version=npo_version,
                    image_channel=npo_channel)
    basic_dict['uri'] = uri_basic = self._GS_IMAGE_PATH_TEMPLATE % basic_dict
    npo_dict['uri'] = uri_npo = self._GS_IMAGE_PATH_TEMPLATE % npo_dict

    expected_basic = gspaths.Image(bucket=self.bucket,
                                   channel=self.channel,
                                   board=self.board,
                                   version=self.version,
                                   image_type=self.signed_image_type,
                                   key=self.key,
                                   uri=uri_basic)
    expected_basic_str = gspaths.ChromeosReleases.ImageName(
        expected_basic.channel, expected_basic.board, expected_basic.version,
        expected_basic.key, expected_basic.image_type)

    expected_npo = gspaths.Image(channel=self.channel,
                                 board=self.board,
                                 version=self.version,
                                 key=self.key,
                                 image_type=self.signed_image_type,
                                 image_channel=npo_channel,
                                 image_version=npo_version,
                                 uri=uri_npo)

    expected_npo_str = gspaths.ChromeosReleases.ImageName(
        expected_npo.image_channel, expected_npo.board,
        expected_npo.image_version, expected_npo.key, expected_npo.image_type)

    basic_image = gspaths.ChromeosReleases.ParseImageUri(uri_basic)
    self.assertEqual(basic_image, expected_basic)
    self.assertEqual(str(basic_image), expected_basic_str)

    npo_image = gspaths.ChromeosReleases.ParseImageUri(uri_npo)
    self.assertEqual(npo_image, expected_npo)
    self.assertEqual(str(npo_image), expected_npo_str)

    signer_output = ('gs://chromeos-releases/dev-channel/link/4537.7.0/'
                     'chromeos_4537.7.1_link_recovery_nplusone-channel_'
                     'mp-v4.bin.1.payload.hash.update_signer.signed.bin')

    bad_image = gspaths.ChromeosReleases.ParseImageUri(signer_output)
    self.assertEqual(bad_image, None)
Ejemplo n.º 4
0
  def testDefaultPayloadUri(self):
    """Test paygen_payload_lib.DefaultPayloadUri."""

    # Test a Full Payload
    result = paygen_payload_lib.DefaultPayloadUri(self.full_payload,
                                                  random_str='abc123')
    self.assertEqual(
        result,
        'gs://chromeos-releases/dev-channel/x86-alex/1620.0.0/payloads/'
        'chromeos_1620.0.0_x86-alex_dev-channel_full_mp-v3.bin-abc123.signed')

    # Test a Delta Payload
    result = paygen_payload_lib.DefaultPayloadUri(self.delta_payload,
                                                  random_str='abc123')
    self.assertEqual(
        result,
        'gs://chromeos-releases/dev-channel/x86-alex/4171.0.0/payloads/'
        'chromeos_1620.0.0-4171.0.0_x86-alex_dev-channel_delta_mp-v3.bin-'
        'abc123.signed')

    # Test an N Plus One Delta Payload
    result = paygen_payload_lib.DefaultPayloadUri(self.nplusone_payload,
                                                  random_str='abc123')
    self.assertEqual(
        result,
        'gs://chromeos-releases/dev-channel/x86-alex/4171.0.0/payloads/'
        'chromeos_4171.0.0-4171.0.1_x86-alex_nplusone-channel_delta_mp-v3.bin-'
        'abc123.signed')

    # Test changing channel, board, and keys
    src_image = gspaths.Image(
        channel='dev-channel',
        board='x86-alex',
        version='3588.0.0',
        key='premp')
    tgt_image = gspaths.Image(
        channel='stable-channel',
        board='x86-alex-he',
        version='3590.0.0',
        key='mp-v3')
    payload = gspaths.Payload(src_image=src_image, tgt_image=tgt_image)

    result = paygen_payload_lib.DefaultPayloadUri(payload,
                                                  random_str='abc123')
    self.assertEqual(
        result,
        'gs://chromeos-releases/stable-channel/x86-alex-he/3590.0.0/payloads/'
        'chromeos_3588.0.0-3590.0.0_x86-alex-he_stable-channel_delta_mp-v3.bin-'
        'abc123.signed')
Ejemplo n.º 5
0
 def testImage_CustomImageType(self):
   custom_image_type = 'base'
   custom_image = gspaths.Image(bucket='bucket',
                                board='board',
                                channel='channel',
                                version='version',
                                image_type=custom_image_type)
   self.assertEquals(custom_image_type, custom_image.image_type)
Ejemplo n.º 6
0
    def setUp(self):
        self.maxDiff = None

        self.prev_build = gspaths.Build(bucket='crt',
                                        channel='foo-channel',
                                        board='foo-board',
                                        version='1.0.0')

        self.prev_image = gspaths.Image(key='mp', **self.prev_build)
        self.prev_premp_image = gspaths.Image(key='premp', **self.prev_build)
        self.prev_test_image = gspaths.UnsignedImageArchive(image_type='test',
                                                            **self.prev_build)

        self.target_build = gspaths.Build(bucket='crt',
                                          channel='foo-channel',
                                          board='foo-board',
                                          version='1.2.3')

        # Create an additional 'special' image like NPO that isn't NPO,
        # and keyed with a weird key. It should match none of the filters.
        self.special_image = gspaths.Image(bucket='crt',
                                           channel='foo-channel',
                                           board='foo-board',
                                           version='1.2.3',
                                           key='foo-key',
                                           image_channel='special-channel')

        self.basic_image = gspaths.Image(key='mp-v2', **self.target_build)
        self.premp_image = gspaths.Image(key='premp', **self.target_build)
        self.test_image = gspaths.UnsignedImageArchive(image_type='test',
                                                       **self.target_build)

        self.mp_full_payload = gspaths.Payload(tgt_image=self.basic_image)
        self.test_full_payload = gspaths.Payload(tgt_image=self.test_image)
        self.mp_delta_payload = gspaths.Payload(tgt_image=self.basic_image,
                                                src_image=self.prev_image)
        self.test_delta_payload = gspaths.Payload(
            tgt_image=self.test_image, src_image=self.prev_test_image)

        self.full_payload_test = paygen_build_lib.PayloadTest(
            self.test_full_payload, self.target_build.channel,
            self.target_build.version)
        self.delta_payload_test = paygen_build_lib.PayloadTest(
            self.test_delta_payload)
Ejemplo n.º 7
0
def GenerateUpdatePayload(tgt_image,
                          payload,
                          src_image=None,
                          work_dir=None,
                          private_key=None,
                          check=None,
                          out_metadata_hash_file=None):
    """Generates output payload and verifies its integrity if needed.

  Args:
    tgt_image: The path (or uri) to the image.
    payload: The path (or uri) to the output payload
    src_image: The path (or uri) to the source image. If passed, a delta payload
        is generated.
    work_dir: A working directory inside the chroot. The None, caller has the
        responsibility to cleanup this directory after this function returns.
    private_key: The private key to sign the payload.
    check: If True, it will check the integrity of the generated payload.
    out_metadata_hash_file: The output metadata hash file.
  """
    tgt_image = gspaths.Image(uri=tgt_image)
    src_image = gspaths.Image(uri=src_image) if src_image else None
    payload = gspaths.Payload(tgt_image=tgt_image,
                              src_image=src_image,
                              uri=payload)
    with chroot_util.TempDirInChroot() as temp_dir:
        work_dir = work_dir if work_dir is not None else temp_dir
        paygen = PaygenPayload(payload,
                               work_dir,
                               sign=private_key is not None,
                               verify=check,
                               private_key=private_key)
        paygen.Run()

        # TODO(ahassani): These are basically a hack because devserver is still need
        # the metadata hash file to sign it. But signing logic has been moved to
        # paygen and in the future this is not needed anymore.
        if out_metadata_hash_file:
            shutil.copy(paygen.metadata_hash_file, out_metadata_hash_file)
Ejemplo n.º 8
0
    def addSignedImage(self, build, key='mp'):
        images = []
        for i in xrange(len(self.signedResults)):
            if build == self.signedResults[i][0]:
                images = self.signedResults[i][1]
                self.signedResults.pop(i)
                break

        image = gspaths.Image(key=key,
                              image_version=build.version,
                              image_type='recovery',
                              **build)
        images.append(image)
        self.signedResults.append((build, images))
        return image
Ejemplo n.º 9
0
  def _DoPrepareImageTest(self, image_type):
    """Test _PrepareImage via mox."""
    download_uri = 'gs://bucket/foo/image.bin'
    image_file = '/work/image.bin'
    test_work_dir = tempfile.gettempdir()  # for testing purposes
    gen = self._GetStdGenerator(work_dir=test_work_dir)

    if image_type == 'Image':
      image_obj = gspaths.Image(
          channel='dev-channel',
          board='x86-alex',
          version='4171.0.0',
          key='mp-v3',
          uri=download_uri)
      test_extract_file = None
    elif image_type == 'UnsignedImageArchive':
      image_obj = gspaths.UnsignedImageArchive(
          channel='dev-channel',
          board='x86-alex',
          version='4171.0.0',
          image_type='test',
          uri=download_uri)
      test_extract_file = paygen_payload_lib._PaygenPayload.TEST_IMAGE_NAME
    else:
      raise ValueError('invalid image type descriptor (%s)' % image_type)

    # Stub out and record the expected function calls.
    self.mox.StubOutWithMock(download_cache.DownloadCache,
                             'GetFileCopy')
    if test_extract_file:
      download_file = mox.IsA(str)
    else:
      download_file = image_file
    self.cache.GetFileCopy(download_uri, download_file)

    if test_extract_file:
      self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
      cros_build_lib.RunCommand(['tar', '-xJf', download_file,
                                 test_extract_file], cwd=test_work_dir)
      self.mox.StubOutWithMock(shutil, 'move')
      shutil.move(os.path.join(test_work_dir, test_extract_file), image_file)

    # Run the test.
    self.mox.ReplayAll()
    gen._PrepareImage(image_obj, image_file)
Ejemplo n.º 10
0
    def _DoPrepareImageTest(self, image_type):
        """Test _PrepareImage."""
        download_uri = 'gs://bucket/foo/image.bin'
        image_file = '/work/image.bin'
        gen = self._GetStdGenerator(work_dir=self.tempdir)

        if image_type == 'Image':
            image_obj = gspaths.Image(build=self.new_build,
                                      key='mp-v3',
                                      uri=download_uri)
            test_extract_file = None
        elif image_type == 'UnsignedImageArchive':
            image_obj = gspaths.UnsignedImageArchive(build=self.new_build,
                                                     image_type='test',
                                                     uri=download_uri)
            test_extract_file = paygen_payload_lib.PaygenPayload.TEST_IMAGE_NAME
        else:
            raise ValueError('invalid image type descriptor (%s)' % image_type)

        # Stub out and Check the expected function calls.
        copy_mock = self.PatchObject(download_cache.DownloadCache,
                                     'GetFileCopy')
        if test_extract_file:
            download_file = mock.ANY
        else:
            download_file = image_file

        if test_extract_file:
            run_mock = self.PatchObject(cros_build_lib, 'run')
            move_mock = self.PatchObject(shutil, 'move')

        # Run the test.
        gen._PrepareImage(image_obj, image_file)

        copy_mock.assert_called_once_with(download_uri, download_file)

        if test_extract_file:
            run_mock.assert_called_once_with(
                ['tar', '-xJf', download_file, test_extract_file],
                cwd=self.tempdir)
            move_mock.assert_called_once_with(
                os.path.join(self.tempdir, test_extract_file), image_file)
Ejemplo n.º 11
0
def _GenSignedGSPath(image, image_type):
    """Take a SignedImage_pb2 and return a gspaths.Image.

  Args:
    image (SignedImage_pb2): The build to create the gspath from.
    image_type (string): The image type, either "recovery" or "base".

  Returns:
    A gspaths.Image instance.
  """
    build = gspaths.Build(board=image.build.build_target.name,
                          version=image.build.version,
                          channel=image.build.channel,
                          bucket=image.build.bucket)

    build_uri = gspaths.ChromeosReleases.ImageUri(build, image.key, image_type)

    build.uri = build_uri

    return gspaths.Image(build=build, image_type=image_type, uri=build_uri)
Ejemplo n.º 12
0
    def setUp(self):
        self.old_build = gspaths.Build(channel='dev-channel',
                                       board='x86-alex',
                                       version='1620.0.0',
                                       bucket='chromeos-releases')

        self.old_image = gspaths.Image(
            build=self.old_build,
            key='mp-v3',
            uri=('gs://chromeos-releases/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_recovery_dev-channel_mp-v3.bin'))

        self.old_base_image = gspaths.Image(
            build=self.old_build,
            key='mp-v3',
            image_type='base',
            uri=('gs://chromeos-releases/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_base_dev-channel_mp-v3.bin'))

        self.new_build = gspaths.Build(channel='dev-channel',
                                       board='x86-alex',
                                       version='4171.0.0',
                                       bucket='chromeos-releases')

        self.new_image = gspaths.Image(
            build=self.new_build,
            key='mp-v3',
            uri=('gs://chromeos-releases/dev-channel/x86-alex/4171.0.0/'
                 'chromeos_4171.0.0_x86-alex_recovery_dev-channel_mp-v3.bin'))

        self.new_dlc_image = gspaths.DLCImage(
            build=self.new_build,
            key='dlc',
            dlc_id='dummy-dlc',
            dlc_package='dummy-package',
            uri=('gs://chromeos-releases/dev-channel/x86-alex/4171.0.0/dlc/'
                 'dummy-dlc/dummy-package/dlc.img'))

        self.old_dlc_image = gspaths.DLCImage(
            build=self.old_build,
            key='dlc',
            dlc_id='dummy-dlc',
            dlc_package='dummy-package',
            uri=('gs://chromeos-releases/dev-channel/x86-alex/1620.0.0/dlc/'
                 'dummy-dlc/dummy-package/dlc.img'))

        self.old_test_image = gspaths.UnsignedImageArchive(
            build=self.old_build,
            uri=('gs://chromeos-releases/dev-channel/x86-alex/1620.0.0/'
                 'chromeos_1620.0.0_x86-alex_recovery_dev-channel_test.bin'))

        self.new_test_image = gspaths.Image(
            build=self.new_build,
            uri=('gs://chromeos-releases/dev-channel/x86-alex/4171.0.0/'
                 'chromeos_4171.0.0_x86-alex_recovery_dev-channel_test.bin'))

        self.full_payload = gspaths.Payload(tgt_image=self.old_base_image,
                                            src_image=None,
                                            uri='gs://full_old_foo/boo')

        self.full_dlc_payload = gspaths.Payload(tgt_image=self.new_dlc_image,
                                                src_image=None,
                                                uri='gs://full_old_foo/boo')

        self.delta_payload = gspaths.Payload(tgt_image=self.new_image,
                                             src_image=self.old_image,
                                             uri='gs://delta_new_old/boo')

        self.delta_dlc_payload = gspaths.Payload(tgt_image=self.new_dlc_image,
                                                 src_image=self.old_dlc_image,
                                                 uri='gs://full_old_foo/boo')

        self.full_test_payload = gspaths.Payload(
            tgt_image=self.old_test_image,
            src_image=None,
            uri='gs://full_old_foo/boo-test')

        self.delta_test_payload = gspaths.Payload(
            tgt_image=self.new_test_image,
            src_image=self.old_test_image,
            uri='gs://delta_new_old/boo-test')
 def testImage_CustomImageType(self):
   custom_image_type = 'base'
   custom_image = gspaths.Image(build=self.build, image_type=custom_image_type)
   self.assertEqual(custom_image_type, custom_image.image_type)
 def testImage_DefaultImageType(self):
   default_image = gspaths.Image(build=self.build)
   self.assertEqual('recovery', default_image.image_type)
 def testIsImage(self):
   a = float(3.14)
   self.assertFalse(gspaths.IsImage(a))
   b = gspaths.Image()
   self.assertTrue(gspaths.IsImage(b))
  def testParsePayloadUri(self):
    """Test gsutils.ChromeosReleases.ParsePayloadUri()."""

    image_version = '1.2.4'

    full_uri = self._Populate(self._GS_FULL_PAYLOAD_PATH_TEMPLATE)

    delta_uri = self._Populate(self._GS_DELTA_PAYLOAD_PATH_TEMPLATE)

    max_full_uri = self._Populate(self._GS_FULL_PAYLOAD_PATH_TEMPLATE,
                                  image_channel='image-channel',
                                  image_version=image_version)

    max_delta_uri = self._Populate(self._GS_DELTA_PAYLOAD_PATH_TEMPLATE,
                                   image_channel='image-channel',
                                   image_version=image_version)

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(full_uri),
        {
            'tgt_image': gspaths.Image(build=self.build, key=self.key),
            'src_image': None,
            'build': self.build,
            'uri': full_uri,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(delta_uri),
        {
            'src_image': gspaths.Image(build=self.src_build),
            'tgt_image': gspaths.Image(build=self.build, key=self.key),
            'build': self.build,
            'uri': delta_uri,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(max_full_uri),
        {
            'tgt_image': gspaths.Image(build=self.build,
                                       key=self.key,
                                       image_version=image_version,
                                       image_channel='image-channel'),
            'src_image': None,
            'build': self.build,
            'uri': max_full_uri,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(max_delta_uri),
        {
            'src_image': gspaths.Image(build=self.src_build),
            'tgt_image': gspaths.Image(build=self.build,
                                       key=self.key,
                                       image_version=image_version,
                                       image_channel='image-channel'),
            'build': self.build,
            'uri': max_delta_uri,
            'exists': False
        })
Ejemplo n.º 17
0
 def testImage_DefaultImageType(self):
   default_image = gspaths.Image(bucket='bucket',
                                 board='board',
                                 channel='channel',
                                 version='version')
   self.assertEquals('recovery', default_image.image_type)
Ejemplo n.º 18
0
  def testParsePayloadUri(self):
    """Test gsutils.ChromeosReleases.ParsePayloadUri()."""

    image_version = '1.2.4'

    full_uri = self._Populate(self._GS_FULL_PAYLOAD_PATH_TEMPLATE,
                              bucket='chromeos-releases')

    delta_uri = self._Populate(self._GS_DELTA_PAYLOAD_PATH_TEMPLATE,
                               bucket='chromeos-releases')

    max_full_uri = self._Populate(self._GS_FULL_PAYLOAD_PATH_TEMPLATE,
                                  image_channel='image-channel',
                                  image_version=image_version)

    max_delta_uri = self._Populate(self._GS_DELTA_PAYLOAD_PATH_TEMPLATE,
                                   image_channel='image-channel',
                                   image_version=image_version)

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(full_uri),
        {
            'tgt_image': gspaths.Image(board=self.board,
                                       channel=self.channel,
                                       version=self.version,
                                       key=self.key),
            'src_image': None,
            'uri': full_uri,
            'labels': [],
            'skip': False,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(delta_uri),
        {
            'src_image': gspaths.Image(board=self.board,
                                       channel=self.channel,
                                       version=self.src_version),
            'tgt_image': gspaths.Image(board=self.board,
                                       channel=self.channel,
                                       version=self.version,
                                       key=self.key),
            'uri': delta_uri,
            'labels': [],
            'skip': False,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(max_full_uri),
        {
            'tgt_image': gspaths.Image(bucket=self.bucket,
                                       board=self.board,
                                       channel=self.channel,
                                       version=self.version,
                                       key=self.key,
                                       image_version=image_version,
                                       image_channel='image-channel'),
            'src_image': None,
            'uri': max_full_uri,
            'labels': [],
            'skip': False,
            'exists': False
        })

    self.assertDictEqual(
        gspaths.ChromeosReleases.ParsePayloadUri(max_delta_uri),
        {
            'src_image': gspaths.Image(bucket=self.bucket,
                                       board=self.board,
                                       channel=self.channel,
                                       version=self.src_version),
            'tgt_image': gspaths.Image(bucket=self.bucket,
                                       board=self.board,
                                       channel=self.channel,
                                       version=self.version,
                                       key=self.key,
                                       image_version=image_version,
                                       image_channel='image-channel'),
            'uri': max_delta_uri,
            'labels': [],
            'skip': False,
            'exists': False
        })