/
extension_service_config_files.go
124 lines (100 loc) · 3.57 KB
/
extension_service_config_files.go
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
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package runtime
import (
"context"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
"github.com/cosi-project/runtime/pkg/controller"
"github.com/cosi-project/runtime/pkg/safe"
"go.uber.org/zap"
v1alpha1runtime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)
// ExtensionServiceConfigFilesController writes down the config files for extension services.
type ExtensionServiceConfigFilesController struct {
V1Alpha1Mode v1alpha1runtime.Mode
ExtensionsConfigBaseDir string
}
// Name implements controller.Controller interface.
func (ctrl *ExtensionServiceConfigFilesController) Name() string {
return "runtime.ExtensionServiceConfigFilesController"
}
// Inputs implements controller.Controller interface.
func (ctrl *ExtensionServiceConfigFilesController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: runtime.NamespaceName,
Type: runtime.ExtensionServiceConfigType,
Kind: controller.InputStrong,
},
}
}
// Outputs implements controller.Controller interface.
func (ctrl *ExtensionServiceConfigFilesController) Outputs() []controller.Output {
return []controller.Output{
{
Type: runtime.ExtensionServiceConfigStatusType,
Kind: controller.OutputExclusive,
},
}
}
// Run implements controller.Controller interface.
//
//nolint:gocyclo
func (ctrl *ExtensionServiceConfigFilesController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
if ctrl.V1Alpha1Mode == v1alpha1runtime.ModeContainer {
return nil
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
list, err := safe.ReaderListAll[*runtime.ExtensionServiceConfig](ctx, r)
if err != nil {
return fmt.Errorf("error listing extension services config: %w", err)
}
r.StartTrackingOutputs()
touchedFiles := map[string]struct{}{}
for iter := list.Iterator(); iter.Next(); {
extensionConfigPath := filepath.Join(ctrl.ExtensionsConfigBaseDir, iter.Value().Metadata().ID())
if err = os.MkdirAll(extensionConfigPath, 0o755); err != nil {
return fmt.Errorf("error creating directory %q: %w", extensionConfigPath, err)
}
touchedFiles[extensionConfigPath] = struct{}{}
for _, file := range iter.Value().TypedSpec().Files {
fileName := filepath.Join(extensionConfigPath, strings.ReplaceAll(strings.TrimPrefix(file.MountPath, "/"), "/", "-"))
if err = updateFile(fileName, []byte(file.Content), 0o644); err != nil {
return fmt.Errorf("error writing file %q: %w", fileName, err)
}
touchedFiles[fileName] = struct{}{}
}
if err = safe.WriterModify(ctx, r, runtime.NewExtensionServiceConfigStatusSpec(runtime.NamespaceName, iter.Value().Metadata().ID()), func(spec *runtime.ExtensionServiceConfigStatus) error {
spec.TypedSpec().SpecVersion = iter.Value().Metadata().Version().String()
return nil
}); err != nil {
return err
}
}
// remove all files not managed by us
if err = filepath.WalkDir(ctrl.ExtensionsConfigBaseDir, func(path string, d fs.DirEntry, walkErr error) error {
if _, ok := touchedFiles[path]; path != ctrl.ExtensionsConfigBaseDir && !ok {
if err = os.RemoveAll(path); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
if err = safe.CleanupOutputs[*runtime.ExtensionServiceConfigStatus](ctx, r); err != nil {
return err
}
}
}