def test_admin_users(self):
        """
        By default, all users that belong to an organization that owns the
        server and OCIM admins have access to the sandbox.
        """
        admin_org_handle = 'admin-org'
        OrganizationFactory(name=admin_org_handle,
                            github_handle=admin_org_handle)

        users = [
            ('user', 'user', admin_org_handle),
            ('admin2', 'admin2', admin_org_handle),
            ('no_github_handle', '', admin_org_handle),
            ('inactive_user', 'inactive_user', admin_org_handle),
            ('another_org', 'another_org', 'another_org'),
            ('no_org_1', 'no_org_1', ''),
            ('no_org_2', 'no_org_2', None),
        ]
        admin_users = [
            ('admin1', 'admin1', admin_org_handle),
            ('admin3', 'admin3', 'another_org'),
            ('admin4', 'admin4', ''),
            ('admin5', 'admin5', None),
            ('admin_no_org', '', admin_org_handle),
            ('inactive_admin', 'inactive_admin', admin_org_handle),
        ]

        expected_admin_users = [
            'user', 'admin1', 'admin2', 'admin3', 'admin4', 'admin5'
        ]

        for username, github_handle, org_handle in users:
            make_user_and_organization(username,
                                       github_username=github_handle,
                                       org_handle=org_handle)

        for username, github_handle, org_handle in admin_users:
            profile, _ = make_user_and_organization(
                username, github_username=github_handle, org_handle=org_handle)
            profile.user.is_superuser = True
            profile.user.save()

        # Mark the inactive user and admin as inactive; they should not be added to the resulting list
        get_user_model().objects.filter(
            username__in=('inactive_user',
                          'inactive_admin')).update(is_active=False)

        instance = OpenEdXInstanceFactory()
        organization = Organization.objects.get(github_handle=admin_org_handle)
        appserver = make_test_appserver(instance, organization=organization)

        self.assertEqual(len(appserver.admin_users), len(expected_admin_users))
        ansible_settings = yaml.load(appserver.configuration_settings)
        self.assertCountEqual(ansible_settings['COMMON_USER_INFO'],
                              [{
                                  'name': name,
                                  'github': True,
                                  'type': 'admin'
                              } for name in expected_admin_users])
Example #2
0
    def test_admin_users(self, mock_consul):
        """
        By default, all users that belong to an organization that owns the
        server and OCIM admins have access to the sandbox.
        """
        admin_org_handle = 'admin-org'
        OrganizationFactory(name=admin_org_handle, github_handle=admin_org_handle)

        users = [
            ('user', 'user', admin_org_handle),
            ('admin2', 'admin2', admin_org_handle),
            ('no_github_handle', '', admin_org_handle),
            ('inactive_user', 'inactive_user', admin_org_handle),
            ('another_org', 'another_org', 'another_org'),
            ('no_org_1', 'no_org_1', ''),
            ('no_org_2', 'no_org_2', None),
        ]
        admin_users = [
            ('admin1', 'admin1', admin_org_handle),
            ('admin3', 'admin3', 'another_org'),
            ('admin4', 'admin4', ''),
            ('admin5', 'admin5', None),
            ('admin_no_org', '', admin_org_handle),
            ('admin_no_github', 'invalid_github_user', admin_org_handle),
            ('inactive_admin', 'inactive_admin', admin_org_handle),
        ]

        expected_admin_users = ['user', 'admin1', 'admin2', 'admin3', 'admin4', 'admin5']

        for username, github_handle, org_handle in users:
            make_user_and_organization(username, github_username=github_handle, org_handle=org_handle)

        for username, github_handle, org_handle in admin_users:
            profile, _ = make_user_and_organization(username, github_username=github_handle, org_handle=org_handle)
            profile.user.is_superuser = True
            profile.user.save()

        # Mark the inactive user and admin as inactive; they should not be added to the resulting list
        get_user_model().objects.filter(username__in=('inactive_user', 'inactive_admin')).update(is_active=False)

        def check(_users):
            return [_user for _user in _users if _user != 'invalid_github_user']

        with patch('instance.models.mixins.openedx_config.check_github_users', check):
            appserver = make_test_appserver(
                OpenEdXInstanceFactory(),
                organization=Organization.objects.get(github_handle=admin_org_handle),
            )

            # Check user with non existant Github hande is removed
            self.assertEqual(len(appserver.admin_users) - 1, len(expected_admin_users))

            ansible_settings = yaml.load(appserver.configuration_settings, Loader=yaml.SafeLoader)
            self.assertCountEqual(ansible_settings['COMMON_USER_INFO'], [
                {'name': name, 'github': True, 'type': 'admin'} for name in expected_admin_users
            ])
Example #3
0
    def test_disabled_watchedfork(self, mock_get_pr_list_from_usernames,
                                  mock_spawn_appserver, mock_get_commit_id_from_ref):
        """
        Creates WatchedFork with the 'enabled' field set to false and checks that its PRs are not watched.
        """

        ansible_extra_settings = textwrap.dedent("""\
            WATCH: true
            edx_ansible_source_repo: https://github.com/open-craft/configuration
            configuration_version: named-release/elder
        """)
        _, organization = make_user_and_organization()
        wf = WatchedForkFactory(
            organization=organization,
            fork='source/repo',
            enabled=False,
        )
        pr = PRFactory(
            number=234,
            source_fork_name='fork/repo',
            target_fork_name=wf.fork,
            branch_name='watch-branch',
            title='Watched PR title which is very long',
            username='******',
            body='Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...'.format(
                ansible_extra_settings
            ),
        )

        mock_get_commit_id_from_ref.return_value = '7' * 40
        mock_get_pr_list_from_usernames.return_value = [pr]

        tasks.watch_pr()
        self.assertEqual(mock_spawn_appserver.call_count, 0)
        self.assertEqual(WatchedPullRequest.objects.count(), 0)
Example #4
0
    def test_create_from_pr(self):
        """
        Create an instance from a pull request
        """
        pr = PRFactory()
        _, organization = make_user_and_organization()
        watched_fork = WatchedForkFactory(fork=pr.fork_name, organization=organization)
        instance, created = WatchedPullRequest.objects.get_or_create_from_pr(pr, watched_fork)
        self.assertTrue(created)

        watched_pr = instance.watchedpullrequest
        self.assertEqual(watched_pr.instance, instance)
        self.assertEqual(watched_pr.github_pr_number, pr.number)
        self.assertEqual(watched_pr.fork_name, pr.fork_name)
        self.assertEqual(watched_pr.branch_name, pr.branch_name)

        internal_lms_domain = 'pr{}.sandbox.basedomain.com'.format(pr.number)
        self.assertEqual(instance.internal_lms_domain, internal_lms_domain)
        self.assertEqual(instance.internal_lms_preview_domain, 'lms-preview.{}'.format(internal_lms_domain))
        self.assertEqual(instance.internal_studio_domain, 'studio-{}'.format(internal_lms_domain))
        self.assertRegex(instance.name, r'^PR')
        self.assertEqual(instance.edx_platform_commit, '9' * 40)

        same_instance, created = WatchedPullRequest.objects.get_or_create_from_pr(pr, watched_fork)
        self.assertEqual(instance, same_instance)
        self.assertFalse(created)
Example #5
0
    def test_create_from_pr_and_watchedfork_values(self):
        """
        Create an instance from a pull request, and check that the default values from the watched fork are used.
        """
        pr = PRFactory()
        _, organization = make_user_and_organization()
        watched_fork = WatchedForkFactory(
            fork=pr.fork_name,
            organization=organization,
            configuration_source_repo_url=
            'https://github.com/open-craft/configuration-fromwatchedfork',
            configuration_version='named-release/elder-fromwatchedfork',
            configuration_extra_settings=textwrap.dedent("""\
                PHRASE: "Hello"
                """),
            openedx_release='ginkgo.8',
        )
        with patch(
                'instance.models.openedx_instance.OpenEdXInstance._write_metadata_to_consul',
                return_value=(1, True)):
            instance, created = WatchedPullRequest.objects.get_or_create_from_pr(
                pr, watched_fork)
        self.assertTrue(created)

        self.assertEqual(
            instance.configuration_source_repo_url,
            'https://github.com/open-craft/configuration-fromwatchedfork')
        self.assertEqual(instance.configuration_version,
                         'named-release/elder-fromwatchedfork')
        self.assertEqual(instance.openedx_release, 'ginkgo.8')
        self.assertEqual(
            yaml.load(instance.configuration_extra_settings,
                      Loader=yaml.SafeLoader), {'PHRASE': 'Hello'})
Example #6
0
 def test_unique_constraints_allow_multiple_per_branch(self):
     """
     Verifies that the unique constraint on a pull request allows for multiple copies of the same branch,
     but different URLs.
     """
     pr = PRFactory()
     _, organization = make_user_and_organization()
     watched_fork = WatchedForkFactory(
         fork=pr.fork_name,
         organization=organization,
         configuration_source_repo_url=
         'https://github.com/open-craft/configuration-fromwatchedfork',
     )
     watched_pr1 = WatchedPullRequest.objects.create(
         github_organization_name='get-by',
         github_repository_name='fork-name',
         branch_name='test',
         github_pr_url='https://github.com/open-craft/opencraft/pull/123/',
         watched_fork=watched_fork,
     )
     watched_pr2 = WatchedPullRequest.objects.create(
         github_organization_name='get-by',
         github_repository_name='fork-name',
         branch_name='test',
         github_pr_url='https://github.com/open-craft/opencraft/pull/1234/',
         watched_fork=watched_fork,
     )
     self.assertNotEqual(watched_pr1, watched_pr2)
Example #7
0
 def test_unique_constraints(self):
     """
     Verifies that we cannot create multiple database entries for following a specific pull request.
     """
     pr = PRFactory()
     _, organization = make_user_and_organization()
     watched_fork = WatchedForkFactory(
         fork=pr.fork_name,
         organization=organization,
         configuration_source_repo_url=
         'https://github.com/open-craft/configuration-fromwatchedfork',
     )
     WatchedPullRequest.objects.create(
         github_organization_name='get-by',
         github_repository_name='fork-name',
         branch_name='test',
         github_pr_url='https://github.com/open-craft/opencraft/pull/123/',
         watched_fork=watched_fork,
     )
     self.assertRaises(
         IntegrityError,
         WatchedPullRequest.objects.create,
         github_organization_name='get-by',
         github_repository_name='fork-name',
         branch_name='test',
         github_pr_url='https://github.com/open-craft/opencraft/pull/123/',
         watched_fork=watched_fork,
     )
Example #8
0
    def test_watch_pr_new(self, mock_get_pr_list_from_usernames,
                          mock_spawn_appserver, mock_get_commit_id_from_ref):
        """
        New PR created on the watched repo
        """
        ansible_extra_settings = textwrap.dedent("""\
            WATCH: true
            edx_ansible_source_repo: https://github.com/open-craft/configuration
            configuration_version: named-release/elder
        """)
        _, organization = make_user_and_organization(github_username='******')
        WatchedForkFactory(organization=organization, fork='source/repo')
        pr = PRFactory(
            number=234,
            source_fork_name='fork/repo',
            target_fork_name='source/repo',
            branch_name='watch-branch',
            title='Watched PR title which is very long',
            username='******',
            body='Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...'.format(
                ansible_extra_settings
            ),
        )
        pr_url = 'https://github.com/source/repo/pull/234'
        self.assertEqual(pr.github_pr_url, pr_url)
        mock_get_pr_list_from_usernames.return_value = [pr]
        mock_get_commit_id_from_ref.return_value = '7' * 40

        tasks.watch_pr()
        self.assertEqual(mock_spawn_appserver.call_count, 1)
        new_instance_ref_id = mock_spawn_appserver.mock_calls[0][1][0]
        instance = OpenEdXInstance.objects.get(ref_set__pk=new_instance_ref_id)
        self.assertEqual(instance.internal_lms_domain, 'pr234.sandbox.awesome.hosting.org')
        self.assertEqual(instance.internal_lms_preview_domain, 'preview.pr234.sandbox.awesome.hosting.org')
        self.assertEqual(instance.internal_studio_domain, 'studio.pr234.sandbox.awesome.hosting.org')
        self.assertEqual(instance.edx_platform_repository_url, 'https://github.com/fork/repo.git')
        self.assertEqual(instance.edx_platform_commit, '7' * 40)
        self.assertEqual(instance.openedx_release, 'master')
        self.assertEqual(
            yaml.load(instance.configuration_extra_settings, Loader=yaml.SafeLoader),
            yaml.load(ansible_extra_settings, Loader=yaml.SafeLoader))
        self.assertEqual(instance.configuration_source_repo_url, 'https://github.com/open-craft/configuration')
        self.assertEqual(instance.configuration_version, 'named-release/elder')
        self.assertEqual(
            instance.name,
            'PR#234: Watched PR title which … (bradenmacdonald) - fork/watch-branch (7777777)')

        # Also check the WatchedPullRequest object:
        watched_pr = WatchedPullRequest.objects.get(github_pr_url=pr_url)
        self.assertEqual(watched_pr.github_pr_number, 234)
        self.assertEqual(watched_pr.github_pr_url, 'https://github.com/source/repo/pull/234')
        self.assertEqual(watched_pr.github_base_url, 'https://github.com/fork/repo')
        self.assertEqual(watched_pr.branch_name, 'watch-branch')
        self.assertEqual(watched_pr.instance_id, instance.id)

        # Once the new instance/appserver has been spawned, it shouldn't spawn again:
        tasks.watch_pr()
        self.assertEqual(mock_spawn_appserver.call_count, 1)
Example #9
0
        def create_test_data(number):
            """
            Return some data about a fork and repository. The data is almost the same, but values have a "1" or "2"
            (or the number you pass) appended. Also, the PR's id is 23001 for PR1, 23002 for PR2 etc.
            """
            pr_extra_settings = textwrap.dedent("""\
                PHRASE: "I am the value defined in PR{}"
                edx_ansible_source_repo: https://github.com/open-craft/configuration
                configuration_version: named-release/elder
            """.format(number))
            _, organization = make_user_and_organization(
                github_username='******')
            wf = WatchedForkFactory(
                organization=organization,
                fork='source/repo{}'.format(number),
                # These 2 values will be replaced by the ones from the PR because the PR ones have more precedence
                configuration_source_repo_url=
                'https://github.com/open-craft/configuration-fromwatchedfork',
                configuration_version='named-release/elder-fromwatchedfork',
                configuration_extra_settings=textwrap.dedent("""\
                PHRASE: "I am a setting which was set up the watched fork {} (but will be overriden by the PR)"
                FORK_SPECIFIC_PHRASE: "I am another setting which was set up in watched fork {}"
                """.format(number, number)),
                openedx_release='ginkgo.8',
            )
            pr_number = 23000 + number
            pr = PRFactory(
                number=pr_number,
                source_fork_name='fork/repo',
                target_fork_name=wf.fork,
                branch_name='watch-branch',
                title='Watched PR title which is very long',
                username='******',
                body=
                'Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...'
                .format(pr_extra_settings),
            )
            pr_url = 'https://github.com/{}/pull/{}'.format(wf.fork, pr_number)
            pr_expected_resulting_settings = {
                'PHRASE':
                "I am the value defined in PR{}".format(number),
                'FORK_SPECIFIC_PHRASE':
                "I am another setting which was set up in watched fork {}".
                format(number),
                'edx_ansible_source_repo':
                'https://github.com/open-craft/configuration',
                'configuration_version':
                'named-release/elder',
            }

            return {
                'wf': wf,
                'pr': pr,
                'url': pr_url,
                'expected_settings': pr_expected_resulting_settings
            }
Example #10
0
 def setUp(self):
     """
     Mock the 'get_commit_id_from_ref' method so it doesn't make a GitHub API call
     """
     super().setUp()
     patcher = patch('pr_watch.models.github.get_commit_id_from_ref')
     self.addCleanup(patcher.stop)
     self.mock_get_commit_id_from_ref = patcher.start()
     self.mock_get_commit_id_from_ref.return_value = '9' * 40
     _, self.organization = make_user_and_organization()
Example #11
0
 def test_get_by_fork_name(self):
     """
     Use `fork_name` to get an instance object from the ORM
     """
     _, organization = make_user_and_organization(org_name="Get by", org_handle="get-by")
     watched_fork = WatchedForkFactory(organization=organization, fork='fork-name')
     WatchedPullRequest.objects.create(
         github_organization_name='get-by',
         github_repository_name='fork-name',
         watched_fork=watched_fork,
     )
     watched_pr = WatchedPullRequest.objects.get(fork_name='get-by/fork-name')
     self.assertEqual(watched_pr.fork_name, 'get-by/fork-name')
Example #12
0
    def test_create_from_pr_and_watchedfork_values(self):
        """
        Create an instance from a pull request, and check that the default values from the watched fork are used.
        """
        pr = PRFactory()
        _, organization = make_user_and_organization()
        watched_fork = WatchedForkFactory(
            fork=pr.fork_name,
            organization=organization,
            ansible_appserver_repo_url=
            'https://github.com/open-craft/ansible-playbooks.git',
            ansible_appserver_playbook='playbooks/appserver.yml',
            ansible_appserver_requirements_path='requirements.txt',
            ansible_appserver_version='ansible2.8.17',
            openstack_server_base_image=
            '{"name_or_id":"focal-20.04-unmodified"}',
            configuration_source_repo_url=
            'https://github.com/open-craft/configuration-fromwatchedfork',
            configuration_version='named-release/elder-fromwatchedfork',
            configuration_extra_settings=textwrap.dedent("""\
                PHRASE: "Hello"
                """),
            openedx_release='ginkgo.8',
        )
        with patch(
                'instance.models.openedx_instance.OpenEdXInstance._write_metadata_to_consul',
                return_value=(1, True)):
            instance, created = WatchedPullRequest.objects.get_or_create_from_pr(
                pr, watched_fork)
        self.assertTrue(created)

        self.assertEqual(
            instance.ansible_appserver_repo_url,
            'https://github.com/open-craft/ansible-playbooks.git')
        self.assertEqual(instance.ansible_appserver_playbook,
                         'playbooks/appserver.yml')
        self.assertEqual(instance.ansible_appserver_requirements_path,
                         'requirements.txt')
        self.assertEqual(instance.ansible_appserver_version, 'ansible2.8.17')
        self.assertEqual(json.loads(instance.openstack_server_base_image),
                         {"name_or_id": "focal-20.04-unmodified"})

        self.assertEqual(
            instance.configuration_source_repo_url,
            'https://github.com/open-craft/configuration-fromwatchedfork')
        self.assertEqual(instance.configuration_version,
                         'named-release/elder-fromwatchedfork')
        self.assertEqual(instance.openedx_release, 'ginkgo.8')
        self.assertEqual(
            yaml.load(instance.configuration_extra_settings,
                      Loader=yaml.SafeLoader), {'PHRASE': 'Hello'})
Example #13
0
    def test_set_fork_name(self):
        """
        Set org & repo using the fork name
        """
        _, organization = make_user_and_organization(org_name="Org2", org_handle="org2")
        watched_fork = WatchedForkFactory(organization=organization, fork='some-name')
        watched_pr = WatchedPullRequest(watched_fork=watched_fork)
        watched_pr.set_fork_name('org2/another-repo')
        self.assertEqual(watched_pr.github_organization_name, 'org2')
        self.assertEqual(watched_pr.github_repository_name, 'another-repo')
        watched_pr.save()

        # Check values in DB
        watched_pr = WatchedPullRequest.objects.get(pk=watched_pr.pk)
        self.assertEqual(watched_pr.github_organization_name, 'org2')
        self.assertEqual(watched_pr.github_repository_name, 'another-repo')
Example #14
0
def make_watched_pr_and_instance(organization=None, **kwargs):
    """
    Create a WatchedPullRequest and associated OpenEdXInstance
    It associates them to the given organization if given, otherwise creates a new one (plus a user).
    """
    pr = PRFactory(**kwargs)

    if not organization:
        # creates user, user profile, and organization needed to be referenced
        _, organization = make_user_and_organization()

    watched_fork = WatchedForkFactory(fork=pr.fork_name,
                                      organization=organization)

    watched_fork.save()
    with patch('pr_watch.github.get_commit_id_from_ref',
               return_value=('5' * 40)):
        instance, dummy = WatchedPullRequest.objects.get_or_create_from_pr(
            pr, watched_fork)
    return instance.watchedpullrequest
Example #15
0
    def test_get_branch_tip_with_tag(self):
        """
        Set the commit id to a tag.

        TODO: Is this 'ref_type' code used for anything?
        """
        self.mock_get_commit_id_from_ref.return_value = 'c' * 40
        _, organization = make_user_and_organization(org_name="Org9",
                                                     org_handle="org9")
        watched_fork = WatchedForkFactory(organization=organization,
                                          fork='org9/repo')
        instance = WatchedPullRequest.objects.create(fork_name='org9/repo',
                                                     branch_name='new-tag',
                                                     ref_type='tag',
                                                     watched_fork=watched_fork)
        self.assertEqual(instance.get_branch_tip(), 'c' * 40)
        self.assertEqual(self.mock_get_commit_id_from_ref.mock_calls, [
            call('org9/repo', 'new-tag', ref_type='tag'),
        ])
        self.assertEqual(instance.branch_name, 'new-tag')
        self.assertEqual(instance.ref_type, 'tag')