Skip to content

Commit 1e79db9

Browse files
committed
make caching simpler and allow to cache steps separately
1 parent a7bea72 commit 1e79db9

File tree

9 files changed

+34
-33
lines changed

9 files changed

+34
-33
lines changed

framework/CACHING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ You can use an environment variable to skip deployment steps and use cached outp
88

99
```
1010
export CTF_CONFIGS=smoke-cache.toml
11-
export CTF_USE_CACHED_OUTPUTS=true
1211
```
1312

1413
### Using remote components
@@ -18,11 +17,13 @@ Because components are decoupled through outputs, you can use a cached config an
1817
Example:
1918
```
2019
[blockchain_a.out]
20+
use_cache = true
2121
chain_id = '31337'
2222
2323
[[blockchain_a.out.nodes]]
2424
ws_url = 'ws://127.0.0.1:33447'
2525
http_url = 'http://127.0.0.1:33447'
2626
docker_internal_ws_url = 'ws://anvil-3716a:8900'
2727
docker_internal_http_url = 'http://anvil-3716a:8900'
28-
```
28+
```
29+
Set flag `use_cache = true` on any component output and run your test again

framework/COMPONENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ type Input struct {
1717
}
1818
1919
type Output struct {
20+
UseCache bool `toml:"use_cache"`
2021
// outputs that will be dumped to config and cached
2122
}
2223
2324
2425
func NewComponent(input *Input) (*Output, error) {
25-
if input.Out != nil && framework.UseCache() {
26+
if input.Out.UseCache {
2627
return input.Out, nil
2728
}
2829
@@ -38,7 +39,7 @@ Each component can define inputs and outputs, following these rules:
3839

3940
- Outputs should be included within inputs.
4041
- If your component is used for side effects output can be omitted.
41-
- `if input.Out != nil && framework.UseCache()` should be added if you'd like to use caching
42+
- `input.Out.UseCache` should be added if you'd like to use caching, see more [here](CACHING.md)
4243

4344
### Docker components good practices for [testcontainers-go](https://golang.testcontainers.org/):
4445

framework/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ This module includes the CTFv2 harness, a lightweight, modular, and data-driven
1515
- **Component isolation**: Components are decoupled via input/output structs, without exposing internal details.
1616
- **Modular configuration**: No arcane knowledge of framework settings is required; the config is simply a reflection of the components being used in the test. Components declare their own configuration—'what you see is what you get.'
1717
- **Replaceability and extensibility**: Since components are decoupled via outputs, any deployment component can be swapped with a real service without altering the test code.
18+
- **Caching**: any component can use cached configs to skip environment setup for faster test development
1819
- **Integrated observability stack**: use `ctf obs up` to spin up a local observability stack.
19-
- **Connectivity**: seamless connection of production-ready components and local components using [testcontainers-go networking](https://golang.testcontainers.org/features/networking/#exposing-host-ports-to-the-container)."
2020

2121

2222
### Environment variables (Tests, when using in Go code)
@@ -28,5 +28,4 @@ This module includes the CTFv2 harness, a lightweight, modular, and data-driven
2828
| LOKI_URL | URL to `Loki` push api, should be like`${host}/loki/api/v1/push` | URL | - | If you use `Loki` then ✅ |
2929
| LOKI_TENANT_ID | Streams all components logs to `Loki`, see params below | `true`, `false` | - | If you use `Loki` then ✅ |
3030
| TESTCONTAINERS_RYUK_DISABLED | Testcontainers-Go reaper container, removes all the containers after the test exit | `true`, `false` | `false` | 🚫 |
31-
| CTF_USE_CACHED_OUTPUTS | Use cached `.out` fields from `*-cache.toml` config | `true`, `false` | `false` | 🚫 |
3231
| RESTY_DEBUG | Log all Resty client HTTP calls | `true`, `false` | `false` | 🚫 |

framework/components/blockchain/anvil.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ func deployAnvil(in *Input) (*Output, error) {
5151
return nil, err
5252
}
5353
return &Output{
54-
ChainID: in.ChainID,
54+
UseCache: true,
55+
ChainID: in.ChainID,
5556
Nodes: []*Node{
5657
{
5758
HostWSUrl: fmt.Sprintf("ws://%s:%s", host, mp.Port()),

framework/components/blockchain/blockchain.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package blockchain
22

33
import (
44
"fmt"
5-
"github.com/smartcontractkit/chainlink-testing-framework/framework"
65
)
76

87
// Input is a blockchain network configuration params
@@ -19,8 +18,9 @@ type Input struct {
1918

2019
// Output is a blockchain network output, ChainID and one or more nodes that forms the network
2120
type Output struct {
22-
ChainID string `toml:"chain_id"`
23-
Nodes []*Node `toml:"nodes"`
21+
UseCache bool `toml:"use_cache"`
22+
ChainID string `toml:"chain_id"`
23+
Nodes []*Node `toml:"nodes"`
2424
}
2525

2626
// Node represents blockchain node output, URLs required for connection locally and inside docker network
@@ -34,21 +34,21 @@ type Node struct {
3434
// NewBlockchainNetwork this is an abstraction that can spin up various blockchain network simulators
3535
// - Anvil
3636
// - Geth
37-
func NewBlockchainNetwork(input *Input) (*Output, error) {
38-
if input.Out != nil && framework.UseCache() {
39-
return input.Out, nil
37+
func NewBlockchainNetwork(in *Input) (*Output, error) {
38+
if in.Out.UseCache {
39+
return in.Out, nil
4040
}
4141
var out *Output
4242
var err error
43-
switch input.Type {
43+
switch in.Type {
4444
case "anvil":
45-
out, err = deployAnvil(input)
45+
out, err = deployAnvil(in)
4646
if err != nil {
4747
return nil, err
4848
}
4949
default:
5050
return nil, fmt.Errorf("blockchain type is not supported or empty")
5151
}
52-
input.Out = out
52+
in.Out = out
5353
return out, nil
5454
}

framework/components/clnode/clnode.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type NodeInput struct {
3636

3737
// Output represents Chainlink node output, nodes and databases connection URLs
3838
type Output struct {
39+
UseCache bool `toml:"use_cache"`
3940
Node *NodeOut `toml:"node"`
4041
PostgreSQL *postgres.Output `toml:"postgresql"`
4142
}
@@ -49,7 +50,7 @@ type NodeOut struct {
4950
// NewNode create a new Chainlink node with some image:tag and one or several configs
5051
// see config params: TestConfigOverrides, UserConfigOverrides, etc
5152
func NewNode(in *Input) (*Output, error) {
52-
if in.Out != nil && framework.UseCache() {
53+
if in.Out != nil && in.Out.UseCache {
5354
return in.Out, nil
5455
}
5556
pgOut, err := postgres.NewPostgreSQL(in.DbInput)
@@ -61,6 +62,7 @@ func NewNode(in *Input) (*Output, error) {
6162
return nil, err
6263
}
6364
out := &Output{
65+
UseCache: true,
6466
Node: nodeOut,
6567
PostgreSQL: pgOut,
6668
}

framework/components/don/don.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package don
22

33
import (
4-
"github.com/smartcontractkit/chainlink-testing-framework/framework"
54
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
65
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/clnode"
76
)
@@ -12,11 +11,12 @@ type Input struct {
1211
}
1312

1413
type Output struct {
15-
Nodes []*clnode.Output `toml:"node"`
14+
UseCache bool `toml:"use_cache"`
15+
Nodes []*clnode.Output `toml:"node"`
1616
}
1717

1818
func NewBasicDON(in *Input, bcOut *blockchain.Output, fakeUrl string) (*Output, error) {
19-
if in.Out != nil && framework.UseCache() {
19+
if in.Out.UseCache {
2020
return in.Out, nil
2121
}
2222
nodeOuts := make([]*clnode.Output, 0)
@@ -34,7 +34,8 @@ func NewBasicDON(in *Input, bcOut *blockchain.Output, fakeUrl string) (*Output,
3434
nodeOuts = append(nodeOuts, o)
3535
}
3636
out := &Output{
37-
Nodes: nodeOuts,
37+
UseCache: true,
38+
Nodes: nodeOuts,
3839
}
3940
in.Out = out
4041
return out, nil

framework/config.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ func noFieldsWithoutRequiredTag(cfg interface{}) []ValidationError {
182182
}
183183
}
184184

185-
// Combine missing "required" tag errors with validation errors
186-
validationErrors = append(validationErrors, checkRequiredTag(cfg, "")...)
185+
// TODO: need more granular approach
186+
//// Combine missing "required" tag errors with validation errors
187+
//validationErrors = append(validationErrors, checkRequiredTag(cfg, "")...)
187188

188189
return validationErrors
189190
}
@@ -300,10 +301,6 @@ func applyEnvConfig(prefix string, input interface{}) error {
300301
return nil
301302
}
302303

303-
func UseCache() bool {
304-
return os.Getenv("CTF_USE_CACHED_OUTPUTS") == "true"
305-
}
306-
307304
func getBaseConfigPath() (string, error) {
308305
configs := os.Getenv("CTF_CONFIGS")
309306
if configs == "" {
@@ -313,13 +310,15 @@ func getBaseConfigPath() (string, error) {
313310
}
314311

315312
func Store[T any](cfg *T) error {
316-
if UseCache() {
317-
return nil
318-
}
319313
baseConfigPath, err := getBaseConfigPath()
320314
if err != nil {
321315
return err
322316
}
317+
newCacheName := strings.Replace(baseConfigPath, ".toml", "", -1)
318+
if strings.Contains(newCacheName, "cache") {
319+
L.Info().Str("Cache", baseConfigPath).Msg("Cache file already exists, skipping")
320+
return nil
321+
}
323322
cachedOutName := fmt.Sprintf("%s-cache.toml", strings.Replace(baseConfigPath, ".toml", "", -1))
324323
L.Info().Str("OutputFile", cachedOutName).Msg("Storing configuration output")
325324
d, err := toml.Marshal(cfg)

framework/promtail.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@ scrape_configs:
105105
}
106106

107107
func NewLokiStreamer() error {
108-
if UseCache() {
109-
return nil
110-
}
111108
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
112109
defer cancel()
113110

0 commit comments

Comments
 (0)