Ejemplo n.º 1
0
    def __init__(self, *args):
        super().__init__(*args)
        self._framework_wrapper = FrameworkWrapper(self.framework, self._state)
        self._resources = {
            'mongodb-image': OCIImageResource('mongodb-image')
        }

        self._mongo_builder = MongoBuilder(
            self._framework_wrapper.app_name,
            self._framework_wrapper.config,
            self._resources,
            self._framework_wrapper.goal_state_units
        )

        if self._framework_wrapper.config['enable-sidecar']:
            self._resources['mongodb-sidecar-image'] = OCIImageResource(
                'mongodb-sidecar-image')

        self._pod = K8sPod(self._framework_wrapper.app_name)
        self._pvc = K8sPvc(self._framework_wrapper.app_name)
        self._mongodb = MongoDbServer(self, "mongo")

        self._k8s_builder = K8sBuilder(self._pvc)

        delegators = [
            (self.on.start, self.on_config_changed_delegator),
            (self.on.upgrade_charm, self.on_config_changed_delegator),
            (self.on.config_changed, self.on_config_changed_delegator),
            (self.on.update_status, self.on_update_status_delegator),
            (self._mongodb.on.new_client, self.on_new_client_delegator),
            (self.on.remove_pvc_action, self.on_remove_pvc_action_delegator),
        ]
        for delegator in delegators:
            self.framework.observe(delegator[0], delegator[1])
    def test_fetch_image_info_succesfully(self):
        # Setup
        mock_resource_name = f"{uuid4()}"

        mock_image_path = f"{uuid4()}/{uuid4()}"
        mock_image_username = f"{uuid4()}"
        mock_image_password = f"{uuid4()}"

        mock_path_obj = MagicMock(Path)
        mock_path_obj.exists.return_value = True
        mock_path_obj.read_text.return_value = f"""
        registrypath: {mock_image_path}
        username: {mock_image_username}
        password: {mock_image_password}
        """

        mock_resources_adapter = MagicMock(Resources)
        mock_resources_adapter.fetch.return_value = mock_path_obj

        # Exercise
        image_resource = OCIImageResource(resource_name=mock_resource_name)
        result = image_resource.fetch(mock_resources_adapter)

        # Assert
        assert mock_resources_adapter.fetch.call_count == 1
        assert mock_resources_adapter.fetch.call_args == \
            call(mock_resource_name)
        assert result
        assert image_resource.image_path == mock_image_path
        assert image_resource.username == mock_image_username
        assert image_resource.password == mock_image_password
Ejemplo n.º 3
0
    def __init__(self, framework, key):
        super().__init__(framework, key)

        for event in (self.on.start, self.on.upgrade_charm,
                      self.on.config_changed, self.on.mysql_relation_changed):
            self.framework.observe(event, self.on_start)
        self.framework.observe(self.on.website_relation_joined, self)

        self.website = HTTPInterfaceProvides(self, 'website')
        self.mysql = MySQLInterfaceRequires(self, 'mysql')
        self.gitlab_image = OCIImageResource(self, 'gitlab_image')
    def test_fetch_image_info_failed(self):
        # Setup
        mock_resource_name = f"{uuid4()}"

        mock_path_obj = MagicMock(Path)
        mock_path_obj.exists.return_value = False

        mock_resources_adapter = MagicMock(Resources)
        mock_resources_adapter.fetch.return_value = mock_path_obj

        # Exercise
        image_resource = OCIImageResource(resource_name=mock_resource_name)

        # Assertions
        with pytest.raises(MissingResourceError):
            assert image_resource.fetch(mock_resources_adapter)
        assert mock_resources_adapter.fetch.call_count == 1
        assert mock_resources_adapter.fetch.call_args == \
            call(mock_resource_name)
    def test_resource_yaml_error(self):
        # Setup
        mock_resource_name = f"{uuid4()}"

        mock_path_obj = MagicMock(Path)
        mock_path_obj.exists.return_value = True
        mock_path_obj.read_text.return_value = f"""
        \0GIBRISH
        """

        mock_resources_adapter = MagicMock(Resources)
        mock_resources_adapter.fetch.return_value = mock_path_obj

        # Exercise
        image_resource = OCIImageResource(resource_name=mock_resource_name)

        # Assertions
        with pytest.raises(InvalidResourceError):
            assert image_resource.fetch(mock_resources_adapter)
        assert mock_resources_adapter.fetch.call_count == 1
        assert mock_resources_adapter.fetch.call_args == \
            call(mock_resource_name)
Ejemplo n.º 6
0
class GitLabK8sCharm(CharmBase):
    state = StoredState()

    def __init__(self, framework, key):
        super().__init__(framework, key)

        for event in (self.on.start, self.on.upgrade_charm,
                      self.on.config_changed, self.on.mysql_relation_changed):
            self.framework.observe(event, self.on_start)
        self.framework.observe(self.on.website_relation_joined, self)

        self.website = HTTPInterfaceProvides(self, 'website')
        self.mysql = MySQLInterfaceRequires(self, 'mysql')
        self.gitlab_image = OCIImageResource(self, 'gitlab_image')

    def on_install(self, event):
        self.state.is_started = False

    def on_start(self, event):
        unit = self.framework.model.unit
        if not self.gitlab_image.fetch():
            unit.status = BlockedStatus('Missing or invalid image resource')
            return
        if not self.mysql.is_joined:
            unit.status = BlockedStatus('Missing database')
        if not self.mysql.is_single:
            unit.status = BlockedStatus('Too many databases')
        if not self.mysql.is_ready:
            unit.status = WaitingStatus('Waiting for database')
            return
        if not self.framework.model.unit.is_leader():
            unit.status = WaitingStatus('Not leader')
            return
        unit.status = MaintenanceStatus('Configuring container')
        self.framework.model.pod.set_spec({
            'containers': [{
                'name':
                self.framework.model.app.name,
                'imageDetails': {
                    'imagePath': self.gitlab_image.registry_path,
                    'username': self.gitlab_image.username,
                    'password': self.gitlab_image.password,
                },
                'ports': [{
                    'containerPort':
                    int(self.framework.model.config['http_port']),
                    'protocol':
                    'TCP',
                }],
                'config': {
                    'GITLAB_OMNIBUS_CONFIG':
                    '; '.join([
                        f"postgresql['enable'] = false",  # disable DB included in image
                        f"gitlab_rails['db_adapter'] = 'mysql2'",
                        f"gitlab_rails['db_encoding'] = 'utf8'",
                        f"gitlab_rails['db_database'] = '{self.mysql.database}'",
                        f"gitlab_rails['db_host'] = '{self.mysql.host}'",
                        f"gitlab_rails['db_port'] = {self.mysql.port}",
                        f"gitlab_rails['db_username'] = '******'",
                        f"gitlab_rails['db_password'] = '******'",
                    ]),
                }
            }],
        })
        self.state.is_started = True
        unit.status = ActiveStatus()

    def on_website_relation_joined(self, event):
        if not self.state.is_started:
            event.defer()
            return

        self.config = self.framework.model.config
        for client in self.website.clients:
            client.serve(hosts=[client.ingress_address],
                         port=self.config['http_port'])