Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to remove wp eval code #216

Merged
merged 4 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src-docs/charm.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ Charm for WordPress on kubernetes.
**Global Variables**
---------------
- **APACHE_LOG_PATHS**
- **WORDPRESS_SCRAPE_JOBS**


---

## <kbd>class</kbd> `WordpressCharm`
Charm for WordPress on kubernetes.

Attrs: state: Persistent charm state used to store metadata after various events.

<a href="../src/charm.py#L137"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="../src/charm.py#L132"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

### <kbd>function</kbd> `__init__`

Expand Down
52 changes: 51 additions & 1 deletion src-docs/cos.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,58 @@ COS integration for WordPress charm.
**Global Variables**
---------------
- **APACHE_PROMETHEUS_SCRAPE_PORT**
- **WORDPRESS_SCRAPE_JOBS**
- **APACHE_LOG_PATHS**
- **REQUEST_DURATION_MICROSECONDS_BUCKETS**


---

## <kbd>class</kbd> `ApacheLogProxyConsumer`
Extends LogProxyConsumer to add a metrics pipeline to promtail.


---

#### <kbd>property</kbd> loki_endpoints

Fetch Loki Push API endpoints sent from LokiPushApiProvider through relation data.



**Returns:**
A list of dictionaries with Loki Push API endpoints, for instance: [
- <b>`{"url"`</b>: "http://loki1:3100/loki/api/v1/push"},
- <b>`{"url"`</b>: "http://loki2:3100/loki/api/v1/push"}, ]

---

#### <kbd>property</kbd> model

Shortcut for more simple access the model.

---

#### <kbd>property</kbd> rsyslog_config

Generates a config line for use with rsyslog.



**Returns:**
The rsyslog config line as a string

---

#### <kbd>property</kbd> syslog_port

Gets the port on which promtail is listening for syslog.



**Returns:**
A str representing the port




---
Expand Down
112 changes: 112 additions & 0 deletions src-docs/state.py.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!-- markdownlint-disable -->

<a href="../src/state.py#L0"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

# <kbd>module</kbd> `state.py`
Wordpress charm state.



---

## <kbd>class</kbd> `CharmConfigInvalidError`
Exception raised when a charm configuration is found to be invalid.



**Attributes:**

- <b>`msg`</b>: Explanation of the error.

<a href="../src/state.py#L25"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

### <kbd>function</kbd> `__init__`

```python
__init__(msg: str)
```

Initialize a new instance of the CharmConfigInvalidError exception.



**Args:**

- <b>`msg`</b>: Explanation of the error.





---

## <kbd>class</kbd> `ProxyConfig`
Configuration for external access through proxy.



**Attributes:**

- <b>`http_proxy`</b>: The http proxy URL.
- <b>`https_proxy`</b>: The https proxy URL.
- <b>`no_proxy`</b>: Comma separated list of hostnames to bypass proxy.




---

<a href="../src/state.py#L47"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

### <kbd>classmethod</kbd> `from_env`

```python
from_env() → Optional[ForwardRef('ProxyConfig')]
```

Instantiate ProxyConfig from juju charm environment.



**Returns:**
ProxyConfig if proxy configuration is provided, None otherwise.


---

## <kbd>class</kbd> `State`
The Wordpress k8s operator charm state.



**Attributes:**

- <b>`proxy_config`</b>: Proxy configuration to access Jenkins upstream through.




---

<a href="../src/state.py#L78"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

### <kbd>classmethod</kbd> `from_charm`

```python
from_charm(_: CharmBase) → State
```

Initialize the state from charm.



**Returns:**
Current state of the charm.



**Raises:**

- <b>`CharmConfigInvalidError`</b>: if invalid state values were encountered.


2 changes: 1 addition & 1 deletion src-docs/types_.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Attrs: return_code: exit code from executed command. stdout: standard output f
## <kbd>class</kbd> `DatabaseConfig`
Configuration values required to connect to database.

Attrs: hostname: The hostname under which the database is being served. database: The name of the database to connect to. username: The username to use to authenticate to the database. password: The password to use to authenticat to the database.
Attrs: hostname: The hostname under which the database is being served. port: The port which the database is listening on. database: The name of the database to connect to. username: The username to use to authenticate to the database. password: The password to use to authenticat to the database.



Expand Down
40 changes: 14 additions & 26 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1178,19 +1178,8 @@ def _plugin_akismet_reconciliation(self) -> None:
f"Unable to config akismet plugin, {result.message}"
)

def _wp_eval(self, php_code: str):
"""Execute arbitrary PHP code.

Args:
php_code: PHP code to be executed.

Returns:
An instance of :attr:`types_.ExecResult`.
"""
return self._wrapped_run_wp_cli(["wp", "eval", php_code])

@staticmethod
def _encode_openid_team_map(team_map: str) -> str:
def _encode_openid_team_map(team_map: str) -> dict:
"""Convert wp_plugin_openid_team_map setting to openid_teams_trust_list WordPress option.

example input: site-sysadmins=administrator,site-editors=editor,site-executives=editor
Expand All @@ -1199,21 +1188,20 @@ def _encode_openid_team_map(team_map: str) -> str:
team_map (str): team definition.

Returns:
A PHP array, as a Python string.
A Python structure that will be converted to json
"""
array_items = []
teams_parsed: dict = {}
for idx, mapping in enumerate(team_map.split(","), start=1):
launchpad_role, wordpress_role = mapping.split("=")
launchpad_role = launchpad_role.strip()
wordpress_role = wordpress_role.strip()
array_items.append(
f"{idx} => (object) array ("
f"'id'=>{idx},"
f"'team'=>'{launchpad_role}',"
f"'role'=>'{wordpress_role}',"
f"'server' => '0',),"
)
return f"array({''.join(array_items)})"
teams_parsed[str(idx)] = {
"id": idx,
"team": launchpad_role,
"role": wordpress_role,
"server": "0",
javierdelapuente marked this conversation as resolved.
Show resolved Hide resolved
}
return teams_parsed

def _plugin_openid_reconciliation(self) -> None:
"""Reconciliation process for the openid plugin."""
Expand Down Expand Up @@ -1254,10 +1242,10 @@ def check_result():
check_result()
result = self._activate_plugin("wordpress-teams-integration", {})
check_result()
result = self._wp_eval(
"update_option("
f"'openid_teams_trust_list', {self._encode_openid_team_map(openid_team_map)}"
");"
result = self._wp_option_update(
"openid_teams_trust_list",
value=json.dumps(self._encode_openid_team_map(openid_team_map)),
format_="json",
)
check_result()
result = self._wp_option_update("users_can_register", "1")
Expand Down
67 changes: 31 additions & 36 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,40 +560,15 @@ def test_team_map():
"""
arrange: no arrange.
act: convert the team_map config using _encode_openid_team_map method.
assert: the converted result should be a valid PHP array with the meaning matching the config.
assert: the converted result should be a valid dict with the meaning matching the config.
"""
team_map = "site-sysadmins=administrator,site-editors=editor,site-executives=editor"
option = WordpressCharm._encode_openid_team_map(team_map)
assert (
option.replace(" ", "").replace("\n", "")
== """array (
1 =>
(object) array(
'id' => 1,
'team' => 'site-sysadmins',
'role' => 'administrator',
'server' => '0',
),
2 =>
(object) array(
'id' => 2,
'team' => 'site-editors',
'role' => 'editor',
'server' => '0',
),
3 =>
(object) array(
'id' => 3,
'team' => 'site-executives',
'role' => 'editor',
'server' => '0',
),
)""".replace(
" ", ""
).replace(
"\n", ""
)
)
assert option == {
"1": {"id": 1, "team": "site-sysadmins", "role": "administrator", "server": "0"},
"2": {"id": 2, "team": "site-editors", "role": "editor", "server": "0"},
"3": {"id": 3, "team": "site-executives", "role": "editor", "server": "0"},
}


def test_swift_config(
Expand Down Expand Up @@ -657,7 +632,7 @@ def test_akismet_plugin(run_standard_plugin_test: typing.Callable):


@pytest.mark.usefixtures("attach_storage")
def test_openid_plugin(patch: WordpressPatch, run_standard_plugin_test: typing.Callable):
def test_openid_plugin(run_standard_plugin_test: typing.Callable):
"""
arrange: after peer relation established and database ready.
act: update openid plugin configuration.
Expand All @@ -669,12 +644,32 @@ def test_openid_plugin(patch: WordpressPatch, run_standard_plugin_test: typing.C
plugin_config={
"wp_plugin_openid_team_map": "site-sysadmins=administrator,site-editors=editor,site-executives=editor"
},
excepted_options={"openid_required_for_registration": "1", "users_can_register": "1"},
excepted_options={
"openid_required_for_registration": "1",
"users_can_register": "1",
"openid_teams_trust_list": {
"1": {
"id": 1,
"role": "administrator",
"server": "0",
"team": "site-sysadmins",
},
"2": {
"id": 2,
"role": "editor",
"server": "0",
"team": "site-editors",
},
"3": {
"id": 3,
"role": "editor",
"server": "0",
"team": "site-executives",
},
},
},
excepted_options_after_removed={"users_can_register": "0"},
)
assert patch.container.wp_eval_history[-1].startswith(
"update_option('openid_teams_trust_list',"
), "PHP function update_option should be invoked after openid plugin enabled"


@pytest.mark.usefixtures("attach_storage")
Expand Down
8 changes: 0 additions & 8 deletions tests/unit/wordpress_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ def __init__(
self._wordpress_database_mock = wordpress_database_mock
self.installed_plugins = set(WordpressCharm._WORDPRESS_DEFAULT_PLUGINS)
self.installed_themes = set(WordpressCharm._WORDPRESS_DEFAULT_THEMES)
self.wp_eval_history: typing.List[str] = []

def exec(
self, cmd, user=None, group=None, working_dir=None, combine_stderr=None, timeout=None
Expand Down Expand Up @@ -602,13 +601,6 @@ def _mock_wp_option_delete(self, cmd):
db.delete_option(option)
return ExecProcessMock(return_code=0, stdout="", stderr="")

@_exec_handler.register(lambda cmd: cmd[:2] == ["wp", "eval"])
def _mock_wp_eval(self, cmd):
"""Simulate ``wp eval <php_code>`` command execution in the container."""
php_code = cmd[2]
self.wp_eval_history.append(php_code)
return ExecProcessMock(return_code=0, stdout="", stderr="")

@_exec_handler.register(lambda cmd: cmd[0] == "a2enconf")
def _mock_a2enconf(self, cmd):
"""Simulate ``a2enconf <conf>`` command execution in the container.
Expand Down
Loading