def test_positive_uploaded_content_library_sync(
        self, module_capsule_configured, function_org, function_product, function_lce_library
    ):
        """Ensure custom repo with no upstream url and manually uploaded
        content after publishing to Library is synchronized to capsule
        automatically

        :id: f5406312-dd31-4551-9f03-84eb9c3415f5

        :customerscenario: true

        :BZ: 1340686

        :expectedresults: custom content is present on external capsule

        :CaseLevel: System
        """
        repo = entities.Repository(product=function_product, url=None).create()
        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce_library.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results']) >= 1
        assert function_lce_library.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Create a content view with the repository
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()

        # Upload custom content into the repo
        with open(get_data_file(constants.RPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        assert repo.read().content_counts['rpm'] == 1

        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        self.wait_for_sync(module_capsule_configured)

        # Verify the RPM published on Capsule
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce_library.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert len(caps_files) == 1
        assert caps_files[0] == constants.RPM_TO_UPLOAD
示例#2
0
    def test_positive_update_with_immediate_sync(self, capsule_configured,
                                                 default_sat):
        """Create a repository with on_demand download policy, associate it
        with capsule, sync repo, update download policy to immediate, sync once
        more.

        :id: 511b531d-1fbe-4d64-ae31-0f9eb6625e7f

        :customerscenario: true

        :BZ: 1315752

        :expectedresults: content was successfully synchronized - capsule
            filesystem contains valid links to packages

        :CaseLevel: System
        """
        repo_url = settings.repos.yum_1.url
        packages_count = constants.FAKE_1_YUM_REPOS_COUNT
        # Create organization, product, repository in satellite, and lifecycle
        # environment
        org = entities.Organization().create()
        prod = entities.Product(organization=org).create()
        repo = entities.Repository(download_policy='on_demand',
                                   mirror_on_sync=True,
                                   product=prod,
                                   url=repo_url).create()
        lce = entities.LifecycleEnvironment(organization=org).create()
        # Update capsule's download policy to on_demand to match repository's
        # policy
        self.update_capsule_download_policy(capsule_configured, 'on_demand')
        # Associate the lifecycle environment with the capsule
        capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': lce.id})
        result = capsule_configured.nailgun_capsule.content_lifecycle_environments(
        )

        assert len(result['results'])
        assert lce.id in [
            capsule_lce['id'] for capsule_lce in result['results']
        ]

        # Create a content view with the repository
        cv = entities.ContentView(organization=org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert len(
            sync_status['active_sync_tasks']) or sync_status['last_sync_time']

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()
        # Update download policy to 'immediate'
        repo.download_policy = 'immediate'
        repo = repo.update(['download_policy'])

        assert repo.download_policy == 'immediate'

        # Update capsule's download policy as well
        self.update_capsule_download_policy(capsule_configured, 'immediate')

        # Sync repository once again
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 2

        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert len(sync_status['active_sync_tasks']
                   ) >= 1 or sync_status['last_sync_time']

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()

        # Verify that new artifacts were created on Capsule
        result = capsule_configured.run(
            'find /var/lib/pulp/media/artifact -type f | wc -l')
        assert int(result.stdout) > packages_count

        # Verify the count of RPMs published on Capsule
        caps_repo_url = form_repo_url(
            capsule_configured,
            org=org.label,
            lce=lce.label,
            cv=cv.label,
            prod=prod.label,
            repo=repo.label,
        )
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert len(caps_files) == packages_count
示例#3
0
    def test_positive_on_demand_sync(self, capsule_configured, default_sat):
        """Create a repository with 'on_demand' policy, add it to a CV,
        promote to an 'on_demand' Capsule's LCE, check artifacts were created,
        download a published package, assert it matches the source.

        :id: ba470269-a7ad-4181-bc7c-8e17a177ca20

        :expectedresults:

            1. A custom yum repository is successfully synced and ContentView published
            2. The ContentView is successfully promoted to the Capsule's LCE and the content
               is automatically synced to the Capsule
            3. Artifacts are created on the Capsule in /var/lib/pulp/media/artifacts/
            4. Package is successfully downloaded from the Capsule, its checksum matches
               the original package from the upstream repo

        :CaseLevel: System
        """
        repo_url = settings.repos.yum_3.url
        packages_count = constants.FAKE_3_YUM_REPOS_COUNT
        package = constants.FAKE_3_YUM_REPO_RPMS[0]
        # Create organization, product, repository in satellite, and lifecycle
        # environment
        org = entities.Organization().create()
        prod = entities.Product(organization=org).create()
        repo = entities.Repository(download_policy='on_demand',
                                   mirror_on_sync=True,
                                   product=prod,
                                   url=repo_url).create()
        lce = entities.LifecycleEnvironment(organization=org).create()
        # Associate the lifecycle environment with the capsule
        capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': lce.id})
        result = capsule_configured.nailgun_capsule.content_lifecycle_environments(
        )

        assert len(result['results'])
        assert lce.id in [
            capsule_lce['id'] for capsule_lce in result['results']
        ]

        # Create a content view with the repository
        cv = entities.ContentView(organization=org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert len(
            sync_status['active_sync_tasks']) or sync_status['last_sync_time']

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()

        # Verify that new artifacts were created on Capsule but rpms were not downloaded
        result = capsule_configured.run(
            'find /var/lib/pulp/media/artifact -type f | wc -l')
        assert 0 < int(result.stdout) < packages_count

        # Verify packages on Capsule match the source
        caps_repo_url = form_repo_url(
            capsule_configured,
            org=org.label,
            lce=lce.label,
            cv=cv.label,
            prod=prod.label,
            repo=repo.label,
        )
        source_files = get_repo_files_by_url(repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert source_files == caps_files
        assert len(caps_files) == packages_count

        # Download a package from the Capsule and get its md5 checksum
        published_package_md5 = md5_by_url(f'{caps_repo_url}/{package}')
        # Get md5 checksum of source package
        package_md5 = md5_by_url(f'{repo_url}/{package}')
        # Assert checksums are matching
        assert package_md5 == published_package_md5
示例#4
0
    def test_positive_capsule_sync(self, capsule_configured, default_sat):
        """Create repository, add it to lifecycle environment, assign lifecycle
        environment with a capsule, sync repository, sync it once again, update
        repository (add 1 new package), sync repository once again.

        :id: 35513099-c918-4a8e-90d0-fd4c87ad2f82

        :customerscenario: true

        :BZ: 1394354, 1439691

        :expectedresults:

            1. Repository sync triggers capsule sync
            2. After syncing capsule contains same repo content as satellite
            3. Syncing repository which has no changes for a second time does
               not trigger any new publish task
            4. Repository revision on capsule remains exactly the same after
               second repo sync with no changes
            5. Syncing repository which was updated will update the content on
               capsule

        :CaseLevel: System
        """
        # Create organization, product, repository in satellite, and lifecycle
        # environment
        repo_url = settings.repos.yum_1.url
        org = entities.Organization(
            smart_proxy=[capsule_configured.nailgun_capsule.id]).create()
        product = entities.Product(organization=org).create()
        repo = entities.Repository(product=product, url=repo_url).create()
        lce = entities.LifecycleEnvironment(organization=org).create()
        # Associate the lifecycle environment with the capsule
        capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': lce.id})
        result = capsule_configured.nailgun_capsule.content_lifecycle_environments(
        )

        assert len(result['results'])
        assert lce.id in [
            capsule_lce['id'] for capsule_lce in result['results']
        ]

        # Create a content view with the repository
        cv = entities.ContentView(organization=org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert len(
            sync_status['active_sync_tasks']) or sync_status['last_sync_time']

        # Content of the published content view in
        # lifecycle environment should equal content of the
        # repository
        assert repo.content_counts['package'] == cvv.package_count

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()
        last_sync_time = sync_status['last_sync_time']

        # Assert that the content published on the capsule is exactly the
        # same as in repository on satellite
        sat_repo_url = form_repo_url(
            default_sat,
            org=org.label,
            lce=lce.label,
            cv=cv.label,
            prod=product.label,
            repo=repo.label,
        )
        caps_repo_url = form_repo_url(
            capsule_configured,
            org=org.label,
            lce=lce.label,
            cv=cv.label,
            prod=product.label,
            repo=repo.label,
        )
        sat_files = get_repo_files_by_url(sat_repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert sat_files == caps_files

        lce_revision_capsule = get_repomd_revision(caps_repo_url)

        # Sync repository for a second time
        result = repo.sync()
        # Assert that the task summary contains a message that says the
        # publish was skipped because content had not changed
        assert result['result'] == 'success'
        assert result['output']['post_action_skipped']
        assert 'Associating Content: 0/0' in result['humanized']['output']

        # Publish a new version of content view
        cv.publish()
        cv = cv.read()
        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        # Promote new content view version to lifecycle environment
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Wait till capsule sync finishes
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()
        tasks = []

        if not sync_status['active_sync_tasks']:
            assert sync_status['last_sync_time'] != last_sync_time
        else:
            for task in sync_status['active_sync_tasks']:
                tasks.append(entities.ForemanTask(id=task['id']))
                tasks[-1].poll()

        # Assert that the value of repomd revision of repository in
        # lifecycle environment on the capsule has not changed
        new_lce_revision_capsule = get_repomd_revision(caps_repo_url)
        assert lce_revision_capsule == new_lce_revision_capsule

        # Update a repository with 1 new rpm
        with open(get_data_file(constants.RPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        # Publish and promote the repository
        repo = repo.read()
        cv.publish()
        cv = cv.read()
        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert (len(sync_status['active_sync_tasks'])
                or sync_status['last_sync_time'] != last_sync_time)

        # Assert that packages count in the repository is updated
        assert repo.content_counts['package'] == (
            constants.FAKE_1_YUM_REPOS_COUNT + 1)

        # Assert that the content of the published content view in
        # lifecycle environment is exactly the same as content of the
        # repository
        assert repo.content_counts['package'] == cvv.package_count

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()

        # Assert that the content published on the capsule is exactly the
        # same as in the repository
        sat_files = get_repo_files_by_url(sat_repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert sat_files == caps_files
示例#5
0
    def test_positive_uploaded_content_library_sync(self, capsule_configured):
        """Ensure custom repo with no upstream url and manually uploaded
        content after publishing to Library is synchronized to capsule
        automatically

        :id: f5406312-dd31-4551-9f03-84eb9c3415f5

        :customerscenario: true

        :BZ: 1340686

        :expectedresults: custom content is present on external capsule

        :CaseLevel: System
        """
        org = entities.Organization(
            smart_proxy=[capsule_configured.nailgun_capsule.id]).create()
        product = entities.Product(organization=org).create()
        repo = entities.Repository(product=product, url=None).create()
        capsule = entities.Capsule(
            id=capsule_configured.nailgun_capsule.id).search(
                query={'search': f'name={capsule_configured.hostname}'})[0]
        # Find "Library" lifecycle env for specific organization
        lce = entities.LifecycleEnvironment(organization=org).search(
            query={'search': f'name={constants.ENVIRONMENT}'})[0]
        # Associate the lifecycle environment with the capsule
        capsule.content_add_lifecycle_environment(
            data={'environment_id': lce.id})
        result = capsule.content_lifecycle_environments()

        assert len(result['results']) >= 1
        assert lce.id in [
            capsule_lce['id'] for capsule_lce in result['results']
        ]

        # Create a content view with the repository
        cv = entities.ContentView(organization=org, repository=[repo]).create()

        # Upload custom content into the repo
        with open(get_data_file(constants.RPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        assert repo.read().content_counts['package'] == 1

        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        # Assert that a task to sync lifecycle environment to the capsule
        # is started (or finished already)
        sync_status = capsule.content_get_sync()
        assert len(sync_status['active_sync_tasks']
                   ) >= 1 or sync_status['last_sync_time']

        # Wait till capsule sync finishes
        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()

        # Verify that new artifacts were created on Capsule
        result = capsule_configured.run(
            'find /var/lib/pulp/media/artifact -type f | wc -l')
        assert int(result.stdout) > 0

        # Verify the RPM published on Capsule
        caps_repo_url = form_repo_url(
            capsule_configured,
            org=org.label,
            lce=lce.label,
            cv=cv.label,
            prod=product.label,
            repo=repo.label,
        )
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert len(caps_files) == 1
        assert caps_files[0] == constants.RPM_TO_UPLOAD
    def test_positive_checksum_sync(self, capsule_configured):
        """Synchronize repository to capsule, update repository's checksum
        type, trigger capsule sync and make sure checksum type was updated on
        capsule

        :id: eb07bdf3-6cd8-4a2f-919b-8dfc84e16115

        :customerscenario: true

        :BZ: 1288656, 1664288, 1732066, 2001052

        :expectedresults: checksum type is updated in repodata of corresponding
            repository on capsule

        :CaseLevel: System

        :CaseImportance: Critical
        """
        # Create organization, product, lce and repository with sha256 checksum
        # type
        org = entities.Organization(
            smart_proxy=[capsule_configured.nailgun_capsule.id]).create()
        product = entities.Product(organization=org).create()
        repo = entities.Repository(
            product=product,
            checksum_type='sha256',
            mirror_on_sync=False,
            download_policy='immediate',
        ).create()
        lce = entities.LifecycleEnvironment(organization=org).create()
        # Associate the lifecycle environment with the capsule
        capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': lce.id})
        result = capsule_configured.nailgun_capsule.content_lifecycle_environments(
        )

        assert len(result['results']) >= 1
        assert lce.id in [
            capsule_lce['id'] for capsule_lce in result['results']
        ]

        # Sync, publish and promote a repo
        cv = entities.ContentView(organization=org, repository=[repo]).create()
        repo.sync()
        repo = repo.read()
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Wait till capsule sync finishes
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert len(sync_status['active_sync_tasks']
                   ) >= 1 or sync_status['last_sync_time']

        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()
        last_sync_time = sync_status['last_sync_time']

        # Verify repodata's checksum type is sha256, not sha1 on capsule
        repo_url = form_repo_url(
            capsule_configured,
            org=org.label,
            prod=product.label,
            repo=repo.label,
            lce=lce.label,
            cv=cv.label,
        )
        repomd = get_repomd(repo_url)
        checksum_types = re.findall(r'(?<=checksum type=").*?(?=")', repomd)
        assert "sha1" not in checksum_types
        assert "sha256" in checksum_types

        # Update repo's checksum type to sha1
        repo.checksum_type = 'sha1'
        repo = repo.update(['checksum_type'])

        # Sync, publish, and promote repo
        repo.sync()
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 2

        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        promote(cvv, lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Wait till capsule sync finishes
        sync_status = capsule_configured.nailgun_capsule.content_get_sync()

        assert (len(sync_status['active_sync_tasks'])
                or sync_status['last_sync_time'] != last_sync_time)

        for task in sync_status['active_sync_tasks']:
            entities.ForemanTask(id=task['id']).poll()

        # Verify repodata's checksum type has updated to sha1 on capsule
        repomd = get_repomd(repo_url)
        checksum_types = re.findall(r'(?<=checksum type=").*?(?=")', repomd)
        assert "sha1" in checksum_types
        assert "sha256" not in checksum_types
    def test_positive_update_with_immediate_sync(
        self, target_sat, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Create a repository with on_demand download policy, associate it
        with capsule, sync repo, update download policy to immediate, sync once
        more.

        :id: 511b531d-1fbe-4d64-ae31-0f9eb6625e7f

        :customerscenario: true

        :BZ: 1315752

        :expectedresults: content was successfully synchronized - capsule
            filesystem contains valid links to packages

        :CaseLevel: System
        """
        repo_url = settings.repos.yum_1.url
        packages_count = constants.FAKE_1_YUM_REPOS_COUNT
        repo = entities.Repository(
            download_policy='on_demand',
            mirroring_policy='mirror_complete',
            product=function_product,
            url=repo_url,
        ).create()
        # Update capsule's download policy to on_demand to match repository's policy
        self.update_capsule_download_policy(module_capsule_configured, 'on_demand')
        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results'])
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Create a content view with the repository
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Update download policy to 'immediate'
        repo.download_policy = 'immediate'
        repo = repo.update(['download_policy'])

        assert repo.download_policy == 'immediate'

        # Update capsule's download policy as well
        self.update_capsule_download_policy(module_capsule_configured, 'immediate')

        # Sync repository once again
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 2

        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Verify the count of RPMs published on Capsule
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert len(caps_files) == packages_count
    def test_positive_on_demand_sync(
        self, target_sat, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Create a repository with 'on_demand' policy, add it to a CV,
        promote to an 'on_demand' Capsule's LCE, download a published package,
        assert it matches the source.

        :id: ba470269-a7ad-4181-bc7c-8e17a177ca20

        :expectedresults:

            1. A custom yum repository is successfully synced and ContentView published
            2. The ContentView is successfully promoted to the Capsule's LCE and the content
               is automatically synced to the Capsule
            3. Package is successfully downloaded from the Capsule, its checksum matches
               the original package from the upstream repo

        :CaseLevel: System
        """
        repo_url = settings.repos.yum_3.url
        packages_count = constants.FAKE_3_YUM_REPOS_COUNT
        package = constants.FAKE_3_YUM_REPO_RPMS[0]
        repo = entities.Repository(
            download_policy='on_demand',
            mirroring_policy='mirror_complete',
            product=function_product,
            url=repo_url,
        ).create()
        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results'])
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Update capsule's download policy to on_demand
        self.update_capsule_download_policy(module_capsule_configured, 'on_demand')

        # Create a content view with the repository
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Verify packages on Capsule match the source
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        source_files = get_repo_files_by_url(repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert source_files == caps_files
        assert len(caps_files) == packages_count

        # Download a package from the Capsule and get its md5 checksum
        published_package_md5 = md5_by_url(f'{caps_repo_url}/{package}')
        # Get md5 checksum of source package
        package_md5 = md5_by_url(f'{repo_url}/{package}')
        # Assert checksums are matching
        assert package_md5 == published_package_md5
    def test_positive_capsule_sync(
        self, target_sat, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Create repository, add it to lifecycle environment, assign lifecycle
        environment with a capsule, sync repository, sync it once again, update
        repository (add 1 new package), sync repository once again.

        :id: 35513099-c918-4a8e-90d0-fd4c87ad2f82

        :customerscenario: true

        :BZ: 1394354, 1439691

        :expectedresults:

            1. Repository sync triggers capsule sync
            2. After syncing capsule contains same repo content as satellite
            3. Syncing repository which has no changes for a second time does
               not trigger any new publish task
            4. Repository revision on capsule remains exactly the same after
               second repo sync with no changes
            5. Syncing repository which was updated will update the content on
               capsule

        :CaseLevel: System
        """
        repo_url = settings.repos.yum_1.url
        repo = entities.Repository(product=function_product, url=repo_url).create()
        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results'])
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Create a content view with the repository
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        # Sync repository
        repo.sync()
        repo = repo.read()
        # Publish new version of the content view
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        # Promote content view to lifecycle environment
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Content of the published content view in
        # lifecycle environment should equal content of the
        # repository
        assert repo.content_counts['rpm'] == cvv.package_count

        self.wait_for_sync(module_capsule_configured)

        # Assert that the content published on the capsule is exactly the
        # same as in repository on satellite
        sat_repo_url = form_repo_url(
            target_sat,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        sat_files = get_repo_files_by_url(sat_repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert sat_files == caps_files

        lce_revision_capsule = get_repomd_revision(caps_repo_url)

        # Sync repository for a second time
        result = repo.sync()
        # Assert that the task summary contains a message that says the
        # sync was skipped because content had not changed
        assert result['result'] == 'success'
        assert 'Skipping Sync (no change from previous sync)' in result['humanized']['output']

        # Publish a new version of content view
        cv.publish()
        cv = cv.read()
        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        # Promote new content view version to lifecycle environment
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Assert that the value of repomd revision of repository in
        # lifecycle environment on the capsule has not changed
        new_lce_revision_capsule = get_repomd_revision(caps_repo_url)
        assert lce_revision_capsule == new_lce_revision_capsule

        # Update a repository with 1 new rpm
        with open(get_data_file(constants.RPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        # Publish and promote the repository
        repo = repo.read()
        cv.publish()
        cv = cv.read()
        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        # Assert that packages count in the repository is updated
        assert repo.content_counts['rpm'] == (constants.FAKE_1_YUM_REPOS_COUNT + 1)

        # Assert that the content of the published content view in
        # lifecycle environment is exactly the same as content of the
        # repository
        assert repo.content_counts['rpm'] == cvv.package_count

        self.wait_for_sync(module_capsule_configured)

        # Assert that the content published on the capsule is exactly the
        # same as in the repository
        sat_files = get_repo_files_by_url(sat_repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert sat_files == caps_files
    def test_positive_sync_updated_repo(
        self, target_sat, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Sync a custom repo with no upstream url but uploaded content to the Capsule via promoted CV,
        update content of the repo, publish and promote the CV again, resync the Capsule.

        :id: ddbecc80-17d9-47f6-979e-111ebd74cb90

        :setup:
            1. Have a custom product, repo without upstream url and LCE created.

        :steps:
            1. Associate the LCE with the Capsule.
            2. Upload some content to the repository.
            3. Create, publish and promote CV with the repository to the Capsule's LCE.
            4. Upload more content to the repository.
            5. Publish new version and promote it to the Capsule's LCE.
            6. Check the Capsule sync result.
            7. Check the content.

        :expectedresults:
            1. Capsule is synced successfully.
            2. Content is present at the Capsule side.

        :CaseLevel: Integration

        :customerscenario: true

        :BZ: 2025494
        """
        repo = entities.Repository(url=None, product=function_product).create()

        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results'])
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Upload custom content into the repo
        with open(get_data_file(constants.RPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        assert repo.read().content_counts['rpm'] == 1

        # Create, publish and promote CV with the repository to the Capsule's LCE
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        cv.publish()
        cv = cv.read()
        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()
        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Upload more content to the repository
        with open(get_data_file(constants.SRPM_TO_UPLOAD), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        assert repo.read().content_counts['rpm'] == 2

        # Publish new version and promote it to the Capsule's LCE.
        cv.publish()
        cv = cv.read()
        assert len(cv.version) == 2

        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()
        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Check the content is synced on the Capsule side properly
        sat_repo_url = form_repo_url(
            target_sat,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        sat_files = get_repo_files_by_url(sat_repo_url)
        caps_files = get_repo_files_by_url(caps_repo_url)
        assert sat_files == caps_files
        assert len(caps_files) == 2
    def test_positive_checksum_sync(
        self, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Synchronize repository to capsule, update repository's checksum
        type, trigger capsule sync and make sure checksum type was updated on
        capsule

        :id: eb07bdf3-6cd8-4a2f-919b-8dfc84e16115

        :customerscenario: true

        :BZ: 1288656, 1664288, 1732066, 2001052

        :expectedresults: checksum type is updated in repodata of corresponding
            repository on capsule

        :CaseLevel: System

        :CaseImportance: Critical
        """
        # Create repository with sha256 checksum type
        repo = entities.Repository(
            product=function_product,
            checksum_type='sha256',
            mirroring_policy='additive',
            download_policy='immediate',
        ).create()
        # Associate the lifecycle environment with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()

        assert len(result['results']) >= 1
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Sync, publish and promote a repo
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        repo.sync()
        repo = repo.read()
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 1

        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Verify repodata's checksum type is sha256, not sha1 on capsule
        repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            prod=function_product.label,
            repo=repo.label,
            lce=function_lce.label,
            cv=cv.label,
        )
        repomd = get_repomd(repo_url)
        checksum_types = re.findall(r'(?<=checksum type=").*?(?=")', repomd)
        assert "sha1" not in checksum_types
        assert "sha256" in checksum_types

        # Update repo's checksum type to sha1
        repo.checksum_type = 'sha1'
        repo = repo.update(['checksum_type'])

        # Sync, publish, and promote repo
        repo.sync()
        cv.publish()
        cv = cv.read()

        assert len(cv.version) == 2

        cv.version.sort(key=lambda version: version.id)
        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()

        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Verify repodata's checksum type has updated to sha1 on capsule
        repomd = get_repomd(repo_url)
        checksum_types = re.findall(r'(?<=checksum type=").*?(?=")', repomd)
        assert "sha1" in checksum_types
        assert "sha256" not in checksum_types
    def test_positive_sync_file_repo(
        self, target_sat, module_capsule_configured, function_org, function_product, function_lce
    ):
        """Sync file-type repository to the capsule.

        :id: 8835c440-016f-408b-8b08-17da8e25a991

        :steps:
            1. Sync file-type repository to Satellite.
            2. Upload one extra file to the repository.
            3. Publish it in a CV, promote to Capsule's LCE.
            4. Check it is synced to Capsule without errors.
            5. Run one more sync, check it succeeds.
            6. Check for content on Satellite and Capsule.

        :expectedresults:
            1. Both capsule syncs succeed.
            2. Content is accessible on both, Satellite and Capsule.

        :CaseLevel: Integration

        :BZ: 1985122
        """
        repo = entities.Repository(
            content_type='file',
            product=function_product,
            url=constants.FAKE_FILE_LARGE_URL,
        ).create()
        repo.sync()

        # Upload one more iso file
        with open(get_data_file(constants.FAKE_FILE_NEW_NAME), 'rb') as handle:
            repo.upload_content(files={'content': handle})

        # Associate LCE with the capsule
        module_capsule_configured.nailgun_capsule.content_add_lifecycle_environment(
            data={'environment_id': function_lce.id}
        )
        result = module_capsule_configured.nailgun_capsule.content_lifecycle_environments()
        assert len(result['results'])
        assert function_lce.id in [capsule_lce['id'] for capsule_lce in result['results']]

        # Create and publish a content view with all repositories
        cv = entities.ContentView(organization=function_org, repository=[repo]).create()
        cv.publish()
        cv = cv.read()
        assert len(cv.version) == 1

        # Promote the latest CV version into capsule's LCE
        cvv = cv.version[-1].read()
        promote(cvv, function_lce.id)
        cvv = cvv.read()
        assert len(cvv.environment) == 2

        self.wait_for_sync(module_capsule_configured)

        # Run one more sync, check for status (BZ#1985122)
        sync_status = module_capsule_configured.nailgun_capsule.content_sync()
        assert sync_status['result'] == 'success'

        # Check for content on SAT and CAPS
        sat_repo_url = form_repo_url(
            target_sat,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        caps_repo_url = form_repo_url(
            module_capsule_configured,
            org=function_org.label,
            lce=function_lce.label,
            cv=cv.label,
            prod=function_product.label,
            repo=repo.label,
        )
        sat_files = get_repo_files_by_url(sat_repo_url, extension='iso')
        caps_files = get_repo_files_by_url(caps_repo_url, extension='iso')
        assert len(sat_files) == len(caps_files) == constants.FAKE_FILE_LARGE_COUNT + 1
        assert constants.FAKE_FILE_NEW_NAME in caps_files
        assert sat_files == caps_files

        for file in sat_files:
            sat_file = md5_by_url(f'{sat_repo_url}{file}')
            caps_file = md5_by_url(f'{caps_repo_url}{file}')
            assert sat_file == caps_file