Skip to content

Commit 18ccd88

Browse files
authored
feat: initial support required extensions (#78)
Introduce a new field in the metadata spec to define a list of required extensions. The generate-testing-values command now automatically includes dependent extensions in the generated values file. Closes #18
1 parent 5578bb5 commit 18ccd88

10 files changed

Lines changed: 89 additions & 19 deletions

File tree

Taskfile.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ tasks:
328328
# We need to replace localhost with the registry container name as it is how
329329
# the registry is reachable from within the Docker network.
330330
sh: sed -E 's/^localhost/{{ .REGISTRY_NAME }}/;t' <<< "{{ .EXTENSION_IMAGE }}"
331+
requires:
332+
vars:
333+
- name: TARGET
331334

332335
e2e:test:
333336
desc: Test target extension using Chainsaw

dagger/maintenance/main.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ func (m *Maintenance) GetTargets(
136136
// Generates Chainsaw's testing external values in YAML format
137137
func (m *Maintenance) GenerateTestingValues(
138138
ctx context.Context,
139+
// The source directory containing the extension folders. Defaults to the current directory
140+
// +ignore=["dagger", ".github"]
141+
// +defaultPath="/"
142+
source *dagger.Directory,
139143
// Path to the target extension directory
140144
target *dagger.Directory,
141145
// URL reference to the extension image to test [REPOSITORY[:TAG]]
@@ -174,18 +178,19 @@ func (m *Maintenance) GenerateTestingValues(
174178
targetExtensionImage)
175179
}
176180

181+
extensions, err := generateTestingValuesExtensions(ctx, source, metadata, targetExtensionImage)
182+
if err != nil {
183+
return nil, err
184+
}
185+
177186
// Build values.yaml content
178187
values := map[string]any{
179188
"name": metadata.Name,
180189
"sql_name": metadata.SQLName,
181-
"image_name": metadata.ImageName,
182190
"shared_preload_libraries": metadata.SharedPreloadLibraries,
183-
"extension_control_path": metadata.ExtensionControlPath,
184-
"dynamic_library_path": metadata.DynamicLibraryPath,
185-
"ld_library_path": metadata.LdLibraryPath,
186-
"extension_image": targetExtensionImage,
187191
"pg_image": pgImage,
188192
"version": version,
193+
"extensions": extensions,
189194
}
190195
valuesYaml, err := yaml.Marshal(values)
191196
if err != nil {

dagger/maintenance/parse.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"path"
78

89
"github.com/docker/buildx/bake"
@@ -28,6 +29,7 @@ type extensionMetadata struct {
2829
DynamicLibraryPath []string `hcl:"dynamic_library_path" cty:"dynamic_library_path"`
2930
LdLibraryPath []string `hcl:"ld_library_path" cty:"ld_library_path"`
3031
AutoUpdateOsLibs bool `hcl:"auto_update_os_libs" cty:"auto_update_os_libs"`
32+
RequiredExtensions []string `hcl:"required_extensions" cty:"required_extensions"`
3133
Versions versionMap `hcl:"versions" cty:"versions"`
3234
Remain hcl.Body `hcl:",remain"`
3335
}
@@ -91,6 +93,14 @@ func parseExtensionMetadata(ctx context.Context, extensionDirectory *dagger.Dire
9193
Remain hcl.Body `hcl:",remain"`
9294
}
9395

96+
hasMetadataFile, err := extensionDirectory.Exists(ctx, metadataFile)
97+
if err != nil {
98+
return nil, err
99+
}
100+
if !hasMetadataFile {
101+
return nil, fmt.Errorf("metadata.hcl file is missing")
102+
}
103+
94104
data, err := extensionDirectory.File(metadataFile).Contents(ctx)
95105
if err != nil {
96106
return nil, err
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"dagger/maintenance/internal/dagger"
8+
)
9+
10+
func generateTestingValuesExtensions(ctx context.Context, source *dagger.Directory, metadata *extensionMetadata, extensionImage string) ([]map[string]any, error) {
11+
var out []map[string]any
12+
configuration, err := generateExtensionConfiguration(metadata, extensionImage)
13+
if err != nil {
14+
return nil, err
15+
}
16+
out = append(out, configuration)
17+
18+
for _, dep := range metadata.RequiredExtensions {
19+
depExists, err := source.Exists(ctx, dep)
20+
if err != nil {
21+
return nil, err
22+
}
23+
if !depExists {
24+
return nil, fmt.Errorf("required dependency %q not found", dep)
25+
}
26+
27+
depMetadata, parseErr := parseExtensionMetadata(ctx, source.Directory(dep))
28+
if parseErr != nil {
29+
return nil, fmt.Errorf("failed to parse dependency metadata %q: %w", dep, parseErr)
30+
}
31+
depsConfiguration, extErr := generateExtensionConfiguration(depMetadata, "")
32+
if extErr != nil {
33+
return nil, extErr
34+
}
35+
out = append(out, depsConfiguration)
36+
}
37+
38+
return out, nil
39+
}
40+
41+
func generateExtensionConfiguration(metadata *extensionMetadata, extensionImage string) (map[string]any, error) {
42+
targetExtensionImage := extensionImage
43+
if targetExtensionImage == "" {
44+
var err error
45+
targetExtensionImage, err = getDefaultExtensionImage(metadata)
46+
if err != nil {
47+
return nil, err
48+
}
49+
}
50+
51+
return map[string]any{
52+
"name": metadata.Name,
53+
"image": map[string]string{
54+
"reference": targetExtensionImage,
55+
},
56+
"extension_control_path": metadata.ExtensionControlPath,
57+
"dynamic_library_path": metadata.DynamicLibraryPath,
58+
"ld_library_path": metadata.LdLibraryPath,
59+
}, nil
60+
}

pgaudit/metadata.hcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ metadata = {
77
dynamic_library_path = []
88
ld_library_path = []
99
auto_update_os_libs = false
10+
required_extensions = []
1011

1112
versions = {
1213
bookworm = {

pgvector/metadata.hcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ metadata = {
77
dynamic_library_path = []
88
ld_library_path = []
99
auto_update_os_libs = false
10+
required_extensions = []
1011

1112
versions = {
1213
bookworm = {

postgis/metadata.hcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ metadata = {
77
dynamic_library_path = []
88
ld_library_path = ["/system"]
99
auto_update_os_libs = true
10+
required_extensions = []
1011

1112
versions = {
1213
bookworm = {

postgis/test/cluster.yaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,4 @@ spec:
1111

1212
postgresql:
1313
shared_preload_libraries: ($values.shared_preload_libraries)
14-
extensions:
15-
- name: ($values.name)
16-
image:
17-
reference: ($values.extension_image)
18-
extension_control_path: ($values.extension_control_path)
19-
dynamic_library_path: ($values.dynamic_library_path)
20-
ld_library_path: ($values.ld_library_path)
14+
extensions: ($values.extensions)

templates/metadata.hcl.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ metadata = {
99
dynamic_library_path = []
1010
ld_library_path = []
1111
auto_update_os_libs = false
12+
required_extensions = []
1213

1314
versions = {
1415
{{- range $distro := .Distros}}

test/cluster.yaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,4 @@ spec:
1111

1212
postgresql:
1313
shared_preload_libraries: ($values.shared_preload_libraries)
14-
extensions:
15-
- name: ($values.name)
16-
image:
17-
reference: ($values.extension_image)
18-
extension_control_path: ($values.extension_control_path)
19-
dynamic_library_path: ($values.dynamic_library_path)
20-
ld_library_path: ($values.ld_library_path)
14+
extensions: ($values.extensions)

0 commit comments

Comments
 (0)