-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathupdatelibs.go
More file actions
125 lines (104 loc) · 3.29 KB
/
updatelibs.go
File metadata and controls
125 lines (104 loc) · 3.29 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
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"context"
"fmt"
"path"
"regexp"
"strings"
"dagger/maintenance/internal/dagger"
)
// libsRegex matches library dependencies from apt-get output
// Format: 'url' library-name size [MD5Sum:checksum]
var libsRegex = regexp.MustCompile(`(?m)^.*\s(lib\S+\.deb)\s+\d+\s*(MD5Sum:\S+)?`)
func updateOSLibsOnTarget(
ctx context.Context,
target string,
distribution string,
majorVersion string,
) (*dagger.File, error) {
postgresBaseImage := fmt.Sprintf("ghcr.io/cloudnative-pg/postgresql:%s-minimal-%s", majorVersion, distribution)
packageName := fmt.Sprintf("postgresql-%s-%s", majorVersion, target)
out, err := dag.Container().
From(postgresBaseImage).
WithUser("root").
WithExec([]string{"apt-get", "update"}).
WithExec([]string{"bash",
"-c",
"apt-get install -qq --print-uris --no-install-recommends " + packageName,
}).Stdout(ctx)
if err != nil {
return nil, fmt.Errorf("failed to fetch OS libs for extension %s (PostgreSQL %s on %s): %w",
target, majorVersion, distribution, err)
}
matches := libsRegex.FindAllStringSubmatch(out, -1)
if len(matches) == 0 {
return nil, fmt.Errorf("no library dependencies found for extension %s (PostgreSQL %s on %s): apt-get may have failed or package has no lib dependencies",
target, majorVersion, distribution)
}
var result string
for _, m := range matches {
line := strings.Join(m[1:], " ")
result += strings.TrimSuffix(line, " ") + "\n"
}
if result == "" {
return nil, fmt.Errorf("parsed empty content for extension %s (PostgreSQL %s on %s): regex matched but extracted no data",
target, majorVersion, distribution)
}
fileName := fmt.Sprintf("%s-%s-os-libs.txt", majorVersion, distribution)
file := dag.File(fileName, result)
return file, nil
}
type extensionsOptions struct {
filterOSLibs bool
}
// ExtensionsOption is a functional option for configuring extension retrieval
type ExtensionsOption func(*extensionsOptions)
// WithOSLibsFilter returns only extensions that have AutoUpdateOsLibs set to true
func WithOSLibsFilter() ExtensionsOption {
return func(opts *extensionsOptions) {
opts.filterOSLibs = true
}
}
// getExtensions retrieves a map of extensions from the source directory.
// By default, all extensions are returned, but filters can be applied.
func getExtensions(
ctx context.Context,
source *dagger.Directory,
opts ...ExtensionsOption,
) (map[string]string, error) {
options := &extensionsOptions{}
for _, opt := range opts {
opt(options)
}
dirs, err := extensionsDirectories(ctx, source)
if err != nil {
return nil, err
}
extensions := make(map[string]string)
for _, dir := range dirs {
metadata, err := parseExtensionMetadata(ctx, dir)
if err != nil {
return nil, err
}
if options.filterOSLibs && !metadata.AutoUpdateOsLibs {
continue
}
dirName, err := dir.Name(ctx)
if err != nil {
return nil, err
}
extensions[path.Dir(dirName)] = metadata.Name
}
return extensions, nil
}
func extensionsDirectories(ctx context.Context, source *dagger.Directory) ([]*dagger.Directory, error) {
paths, err := source.Glob(ctx, path.Join("**", metadataFile))
if err != nil {
return nil, err
}
directories := make([]*dagger.Directory, 0, len(paths))
for _, p := range paths {
directories = append(directories, source.Directory(path.Dir(p)))
}
return directories, nil
}