Skip to content

TPT-4130: Add Valkey Managed Database integration tests - #932

Draft
anmsharm1 wants to merge 6 commits into
linode:devfrom
anmsharm1:DBAAS1-1774
Draft

anmsharm1 wants to merge 6 commits into
linode:devfrom
anmsharm1:DBAAS1-1774

Conversation

@anmsharm1

Copy link
Copy Markdown

📝 Description

What does this PR do and why is this change necessary?

Adds integration test coverage for Valkey Managed Databases, including engine and type discovery, database listing and viewing, engine configuration, credentials and SSL, suspend/resume, patching, and snapshot-based fork/restore.

Adds table output handling for valkey-config-view, including readable formatting for nullable configuration parameter types ( backup_minute,  backup_hour, valkey_memory_policy etc. ), such as integer | null or string | null. This is required as Valkey’s config schema includes nullable parameter types represented as lists, such as  ["integer", "null"] .

The new formatting helper renders those as  integer | null.  I modeled add_param_row that now  applies that formatting only when the Valkey handler opts in otherwise its default preserves the existing type formatting for PostgreSQL and MySQL.

✔️ How to Test

What are the steps to reproduce the issue or verify the changes?

Set LINODE_CLI_TOKEN to a token for an account that can create Managed Databases. The integration tests create and delete live database resources. Snapshot restore is skipped by default; set RUN_LONG_TESTS=True to run it.

How do I run the relevant unit/integration tests?

  • make test-unit — passed.
  • make test-int TEST_SUITE=database TEST_CASE=valkey TEST_ARGS='-v' — 10 passed, 1 skipped, 17 deselected.

anmsharm1 and others added 6 commits September 29, 2026 12:17
Render nullable types as a readable union in database configuration tables. Cover Valkey output without changing non-nullable types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread linodecli/overrides.py


def add_param_row(output, param_name, param_data):
def _format_param_type(param_type) -> str:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: not sure how consistently the convention is followed in this repo, but in this module at least it looks like the step-down rule more-or-less applies, which means this should follow add_param_row().

}

with patch("linodecli.overrides.Console", return_value=MockConsole()):
assert databases_valkey_config_view_output(response_json) is False

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: assert not databases_valkey_config_view_output(response_json)? (I do see is False assertions elsewhere in the repo, but I gather they're intended specifically to verify that the human-facing output from the tool is actually False rather than merely something falsy, which is a distinction that I suspect does not matter for this function.)

Comment thread linodecli/overrides.py


def add_param_row(output, param_name, param_data):
def _format_param_type(param_type) -> str:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is intentional, but it's worth noting in this context that the logic here makes the behavior for Valkey parameters with multiple types different from the other engines. I can't immediately produce an example for PostgreSQL, which is currently broken in the CLI (!), but I can for MySQL:

├────────────────────────────────┼────────────────────┼────────────────────┼─────────┼──────────────────────┼────────────┼────────────┼───────────────────────┼──────────────────┼────────────────────────────────┤
│ mysql.innodb_ft_server_stopwo… │ ['null', 'string'] │ db_name/table_name │         │                      │            │    1024    │        ^.+/.+$        │        NO        │ This option is used to specify │
│                                │                    │                    │         │                      │            │            │                       │                  │ your own InnoDB FULLTEXT index │
│                                │                    │                    │         │                      │            │            │                       │                  │ stopword list for all InnoDB   │
│                                │                    │                    │         │                      │            │            │                       │                  │ tables.                        │
├────────────────────────────────┼────────────────────┼────────────────────┼─────────┼──────────────────────┼────────────┼────────────┼───────────────────────┼──────────────────┼────────────────────────────────┤

... where the type of the parameter would be given as null | string for Valkey.

Maybe this is a question best addressed to the maintainers, but: what's the right thing to do here? Aim for consistency across the engine types? If so, should MySQL + (presumably) PG switch to the formatting applied here, or should Valkey use the existing formatting?

)
assert isinstance(config[key]["requires_restart"], bool)

assert config["backup_hour"]["minimum"] == 0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to assert on the values of these fields? I think it's reasonable to expect that the config fields available at launch will be available indefinitely (as tossing any would be breaking), but I don't think it's safe to assume that min, max, requires_restart, etc. values won't change over time. We don't want these tests to break because, e.g., Aiven decided to widen the permitted range for one of them. (Maybe similar goes for the expected types above, at least inasmuch as some that may not currently be nullable may become nullable in the future.)

)

wait_for_condition(15, 900, config_matches)
valkey_cluster["engine_config"].update(updated_config)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the wait above fails, this line won't execute. Is that okay, or might it cause additional test failures?

+ ["valkey-resume", database_id, "--text", "--delimiter=,"]
)
assert "Request failed: 400" not in res
wait_for_database_status("valkey", database_id, "active")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added step for Valkey will add on the order of minutes of latency relative to the MySQL/PG tests, likely similar to the added cost of forking... which suggests that the RUNG_LONG_TESTS guard might be applicable here. (Do we know what the threshold is beyond which it should be applied?)


def test_valkey_suspend_resume(valkey_cluster):
database_id = str(valkey_cluster["id"])
wait_for_database_status("valkey", database_id, "active")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, it feels a little odd to wait for active status both at the start and the end of the tests. I'd naively expect either that tests that need the instance in active status would consistently wait for that at the start or that tests moving the database out of active would consistently wait for that, e.g., at teardown. (Which ultimately sounds like a fixture to me, I think.)



@pytest.fixture(scope="session")
def valkey_cluster():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach in valkey_cluster() feels like an improvement to me relative to the other database engines -- being flexible about the type, region, and engine; making sure the instance is ready before use; and sharing more details with the tests that consume the instance all seem like facially good, reasonable choices -- but there are tradeoffs that are worth explicitly considering, I think.

  • One is whether we want to leave the CLI in a state where Valkey is treated very differently from PostgreSQL and MySQL. That's potentially both a maintainability issue and a source of inconsistency in the quality of the products. A plausible answer to that is to line up PG and MySQL with Valkey, though -- either in this PR or in a followup -- rather than to move in the other direction.
  • Another is how comprehensive these tests are intended to be/should be. Some of the testing here arguably veers into testing the Managed Database functionality itself, which might be more than we want from these tests. The additional complexity and coverage here carries some maintenance burden that's worth taking into account. Probably this question is mostly for the maintainers.
  • Somewhat relatedly: some of these steps will nontrivially increase the running time of the tests. Probably not a huge deal, but FWIW it may mean we should be more aggressive about treating these tests as long-running.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants