-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsecrets_with_devbox.py
More file actions
112 lines (93 loc) · 3.51 KB
/
Copy pathsecrets_with_devbox.py
File metadata and controls
112 lines (93 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env -S uv run python
"""
---
title: Secrets with Devbox (Create, Inject, Verify, Delete)
slug: secrets-with-devbox
use_case: Create a secret, inject it into a devbox as an environment variable, verify access, and clean up.
workflow:
- Create a secret with a test value
- Create a devbox with the secret mapped to an env var
- Execute a command that reads the secret from the environment
- Verify the value matches
- Update the secret and verify
- List secrets and verify the secret appears
- Shutdown devbox and delete secret
tags:
- secrets
- devbox
- environment-variables
- cleanup
prerequisites:
- RUNLOOP_API_KEY
run: uv run python -m examples.secrets_with_devbox
test: uv run pytest -m smoketest tests/smoketests/examples/
---
"""
from __future__ import annotations
from runloop_api_client import RunloopSDK
from ._harness import run_as_cli, unique_name, wrap_recipe
from .example_types import ExampleCheck, RecipeOutput, RecipeContext
# Note: do NOT hardcode secret values in your code!
# This is example code only; use environment variables instead!
_EXAMPLE_SECRET_VALUE = "my-secret-value"
_UPDATED_SECRET_VALUE = "updated-secret-value"
def recipe(ctx: RecipeContext) -> RecipeOutput:
"""Create a secret, inject it into a devbox, and verify it is accessible."""
cleanup = ctx.cleanup
sdk = RunloopSDK()
resources_created: list[str] = []
checks: list[ExampleCheck] = []
secret_name = unique_name("RUNLOOP_SDK_EXAMPLE").upper().replace("-", "_")
secret = sdk.secret.create(name=secret_name, value=_EXAMPLE_SECRET_VALUE)
resources_created.append(f"secret:{secret_name}")
cleanup.add(f"secret:{secret_name}", lambda: secret.delete())
secret_info = secret.get_info()
checks.append(
ExampleCheck(
name="secret created successfully",
passed=secret.name == secret_name and secret_info.id.startswith("sec_"),
details=f"name={secret.name}, id={secret_info.id}",
)
)
devbox = sdk.devbox.create(
name=unique_name("secrets-example-devbox"),
secrets={
"MY_SECRET_ENV": secret.name,
},
launch_parameters={
"resource_size_request": "X_SMALL",
"keep_alive_time_seconds": 60 * 5,
},
)
resources_created.append(f"devbox:{devbox.id}")
cleanup.add(f"devbox:{devbox.id}", devbox.shutdown)
result = devbox.cmd.exec("echo $MY_SECRET_ENV")
stdout = result.stdout().strip()
checks.append(
ExampleCheck(
name="devbox can read secret as env var",
passed=result.exit_code == 0 and stdout == _EXAMPLE_SECRET_VALUE,
details=f'exit_code={result.exit_code}, stdout="{stdout}"',
)
)
updated_info = sdk.secret.update(secret, _UPDATED_SECRET_VALUE).get_info()
checks.append(
ExampleCheck(
name="secret updated successfully",
passed=updated_info.name == secret_name,
details=f"update_time_ms={updated_info.update_time_ms}",
)
)
secrets = sdk.secret.list()
found = next((s for s in secrets if s.name == secret_name), None)
checks.append(
ExampleCheck(
name="secret appears in list",
passed=found is not None,
details=f"found name={found.name}" if found else "not found",
)
)
return RecipeOutput(resources_created=resources_created, checks=checks)
run_secrets_with_devbox_example = wrap_recipe(recipe)
if __name__ == "__main__":
run_as_cli(run_secrets_with_devbox_example)