Skip to content

Commit

Permalink
feat: support environment in ExtensionServicesConfig
Browse files Browse the repository at this point in the history
Support setting extension services environment variables in
`ExtensionServiceConfig` document.

Refactor `ExtensionServicesConfig` -> `ExtensionServiceConfig` and move extensions config under `runtime` pkg.

Fixes: #8271

Signed-off-by: Noel Georgi <git@frezbo.dev>
  • Loading branch information
frezbo committed Feb 15, 2024
1 parent 3fe82ec commit 15e8bca
Show file tree
Hide file tree
Showing 45 changed files with 1,069 additions and 668 deletions.
Binary file modified api/api.descriptors
Binary file not shown.
15 changes: 8 additions & 7 deletions api/resource/definitions/runtime/runtime.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ message EventSinkConfigSpec {
string endpoint = 1;
}

// ExtensionServicesConfigFile describes extensions service config files.
message ExtensionServicesConfigFile {
// ExtensionServiceConfigFile describes extensions service config files.
message ExtensionServiceConfigFile {
string content = 1;
string mount_path = 2;
}

// ExtensionServicesConfigSpec describes status of rendered extensions service config files.
message ExtensionServicesConfigSpec {
repeated ExtensionServicesConfigFile files = 2;
// ExtensionServiceConfigSpec describes status of rendered extensions service config files.
message ExtensionServiceConfigSpec {
repeated ExtensionServiceConfigFile files = 1;
repeated string environment = 2;
}

// ExtensionServicesConfigStatusSpec describes status of rendered extensions service config files.
message ExtensionServicesConfigStatusSpec {
// ExtensionServiceConfigStatusSpec describes status of rendered extensions service config files.
message ExtensionServiceConfigStatusSpec {
string spec_version = 1;
}

Expand Down
5 changes: 5 additions & 0 deletions cmd/talosctl/cmd/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/types/network"
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime"
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime/extensions"
"github.com/siderolabs/talos/pkg/machinery/config/types/siderolink"
v1alpha1 "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
)
Expand Down Expand Up @@ -120,6 +121,10 @@ var docsCmd = &cobra.Command{
name: "v1alpha1",
fileDoc: v1alpha1.GetFileDoc(),
},
{
name: "extensions",
fileDoc: extensions.GetFileDoc(),
},
} {
path := filepath.Join(dir, pkg.name)

Expand Down
17 changes: 10 additions & 7 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,22 @@ Talos Linux now supports OpenNebula platform.
[notes.extensions]
title = "Extension Services Config"
description = """\
Talos now supports supplying configuration files for extension services that can be mounted into the extension service container.
Talos now supports supplying configuration files and environment variables for extension services.
The extension service configuration is a separate config document. An example is shown below:
```yaml
---
apiVersion: v1alpha1
kind: ExtensionServicesConfig
config:
- name: nut-client
configFiles:
- content: MONITOR ${upsmonHost} 1 remote pass password
mountPath: /usr/local/etc/nut/upsmon.conf
kind: ExtensionServiceConfig
name: nut-client
configFiles:
- content: MONITOR ${upsmonHost} 1 remote pass password
mountPath: /usr/local/etc/nut/upsmon.conf
environment:
- UPS_NAME=ups
```
For documentation, see [Extension Services Config Files](https://www.talos.dev/v1.7/reference/configuration/extensions/extensionserviceconfig/).
"""

[notes.k8supgrade]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (ctrl *ExtensionServiceController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: runtime.NamespaceName,
Type: runtime.ExtensionServicesConfigStatusType,
Type: runtime.ExtensionServiceConfigStatusType,
Kind: controller.InputStrong,
},
}
Expand Down Expand Up @@ -84,7 +84,7 @@ func (ctrl *ExtensionServiceController) Run(ctx context.Context, r controller.Ru

// load initial state of configStatuses
if ctrl.configStatusCache == nil {
configStatuses, err := safe.ReaderListAll[*runtime.ExtensionServicesConfigStatus](ctx, r)
configStatuses, err := safe.ReaderListAll[*runtime.ExtensionServiceConfigStatus](ctx, r)
if err != nil {
return fmt.Errorf("error listing extension services config: %w", err)
}
Expand Down Expand Up @@ -146,7 +146,7 @@ func (ctrl *ExtensionServiceController) Run(ctx context.Context, r controller.Ru
case <-r.EventCh():
}

configStatuses, err := safe.ReaderListAll[*runtime.ExtensionServicesConfigStatus](ctx, r)
configStatuses, err := safe.ReaderListAll[*runtime.ExtensionServiceConfigStatus](ctx, r)
if err != nil {
return fmt.Errorf("error listing extension services config: %w", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ import (
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)

// ExtensionServicesConfigController watches v1alpha1.Config, creates/updates/deletes extension services config.
type ExtensionServicesConfigController struct{}
// ExtensionServiceConfigController watches v1alpha1.Config, creates/updates/deletes extension services config.
type ExtensionServiceConfigController struct{}

// Name implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigController) Name() string {
return "runtime.ExtensionServicesConfigController"
func (ctrl *ExtensionServiceConfigController) Name() string {
return "runtime.ExtensionServiceConfigController"
}

// Inputs implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigController) Inputs() []controller.Input {
func (ctrl *ExtensionServiceConfigController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: config.NamespaceName,
Expand All @@ -41,10 +41,10 @@ func (ctrl *ExtensionServicesConfigController) Inputs() []controller.Input {
}

// Outputs implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigController) Outputs() []controller.Output {
func (ctrl *ExtensionServiceConfigController) Outputs() []controller.Output {
return []controller.Output{
{
Type: runtime.ExtensionServicesConfigType,
Type: runtime.ExtensionServiceConfigType,
Kind: controller.OutputExclusive,
},
}
Expand All @@ -53,7 +53,7 @@ func (ctrl *ExtensionServicesConfigController) Outputs() []controller.Output {
// Run implements controller.Controller interface.
//
//nolint:gocyclo
func (ctrl *ExtensionServicesConfigController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
func (ctrl *ExtensionServiceConfigController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
for {
select {
case <-ctx.Done():
Expand All @@ -68,24 +68,26 @@ func (ctrl *ExtensionServicesConfigController) Run(ctx context.Context, r contro

r.StartTrackingOutputs()

if cfg != nil && cfg.Config() != nil && cfg.Config().ExtensionServicesConfig() != nil {
for _, ext := range cfg.Config().ExtensionServicesConfig().ConfigData() {
if err = safe.WriterModify(ctx, r, runtime.NewExtensionServicesConfigSpec(runtime.NamespaceName, ext.Name()), func(spec *runtime.ExtensionServicesConfig) error {
spec.TypedSpec().Files = xslices.Map(ext.ConfigFiles(), func(c extconfig.ExtensionServicesConfigFile) runtime.ExtensionServicesConfigFile {
return runtime.ExtensionServicesConfigFile{
if cfg != nil && cfg.Config() != nil {
for _, extConfig := range cfg.Config().ExtensionServiceConfigs() {
if err = safe.WriterModify(ctx, r, runtime.NewExtensionServiceConfigSpec(runtime.NamespaceName, extConfig.Name()), func(spec *runtime.ExtensionServiceConfig) error {
spec.TypedSpec().Files = xslices.Map(extConfig.ConfigFiles(), func(c extconfig.ExtensionServiceConfigFile) runtime.ExtensionServiceConfigFile {
return runtime.ExtensionServiceConfigFile{
Content: c.Content(),
MountPath: c.Path(),
MountPath: c.MountPath(),
}
})

spec.TypedSpec().Environment = extConfig.Environment()

return nil
}); err != nil {
return err
}
}
}

if err = safe.CleanupOutputs[*runtime.ExtensionServicesConfig](ctx, r); err != nil {
if err = safe.CleanupOutputs[*runtime.ExtensionServiceConfig](ctx, r); err != nil {
return err
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,33 @@ import (
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)

// ExtensionServicesConfigFilesController writes down the config files for extension services.
type ExtensionServicesConfigFilesController struct {
// ExtensionServiceConfigFilesController writes down the config files for extension services.
type ExtensionServiceConfigFilesController struct {
V1Alpha1Mode v1alpha1runtime.Mode
ExtensionsConfigBaseDir string
}

// Name implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigFilesController) Name() string {
return "runtime.ExtensionServicesConfigFilesController"
func (ctrl *ExtensionServiceConfigFilesController) Name() string {
return "runtime.ExtensionServiceConfigFilesController"
}

// Inputs implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigFilesController) Inputs() []controller.Input {
func (ctrl *ExtensionServiceConfigFilesController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: runtime.NamespaceName,
Type: runtime.ExtensionServicesConfigType,
Type: runtime.ExtensionServiceConfigType,
Kind: controller.InputStrong,
},
}
}

// Outputs implements controller.Controller interface.
func (ctrl *ExtensionServicesConfigFilesController) Outputs() []controller.Output {
func (ctrl *ExtensionServiceConfigFilesController) Outputs() []controller.Output {
return []controller.Output{
{
Type: runtime.ExtensionServicesConfigStatusType,
Type: runtime.ExtensionServiceConfigStatusType,
Kind: controller.OutputExclusive,
},
}
Expand All @@ -55,7 +55,7 @@ func (ctrl *ExtensionServicesConfigFilesController) Outputs() []controller.Outpu
// Run implements controller.Controller interface.
//
//nolint:gocyclo
func (ctrl *ExtensionServicesConfigFilesController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
func (ctrl *ExtensionServiceConfigFilesController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
if ctrl.V1Alpha1Mode == v1alpha1runtime.ModeContainer {
return nil
}
Expand All @@ -67,7 +67,7 @@ func (ctrl *ExtensionServicesConfigFilesController) Run(ctx context.Context, r c
case <-r.EventCh():
}

list, err := safe.ReaderListAll[*runtime.ExtensionServicesConfig](ctx, r)
list, err := safe.ReaderListAll[*runtime.ExtensionServiceConfig](ctx, r)
if err != nil {
return fmt.Errorf("error listing extension services config: %w", err)
}
Expand Down Expand Up @@ -95,7 +95,7 @@ func (ctrl *ExtensionServicesConfigFilesController) Run(ctx context.Context, r c
touchedFiles[fileName] = struct{}{}
}

if err = safe.WriterModify(ctx, r, runtime.NewExtensionServicesConfigStatusSpec(runtime.NamespaceName, iter.Value().Metadata().ID()), func(spec *runtime.ExtensionServicesConfigStatus) error {
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
Expand All @@ -117,7 +117,7 @@ func (ctrl *ExtensionServicesConfigFilesController) Run(ctx context.Context, r c
return err
}

if err = safe.CleanupOutputs[*runtime.ExtensionServicesConfigStatus](ctx, r); err != nil {
if err = safe.CleanupOutputs[*runtime.ExtensionServiceConfigStatus](ctx, r); err != nil {
return err
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ import (
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)

type ExtensionServicesConfigFilesSuite struct {
type ExtensionServiceConfigFilesSuite struct {
ctest.DefaultSuite
extensionsConfigDir string
}

func TestExtensionServicesConfigFilesSuite(t *testing.T) {
func TestExtensionServiceConfigFilesSuite(t *testing.T) {
extensionsConfigDir := t.TempDir()

suite.Run(t, &ExtensionServicesConfigFilesSuite{
suite.Run(t, &ExtensionServiceConfigFilesSuite{
DefaultSuite: ctest.DefaultSuite{
AfterSetup: func(suite *ctest.DefaultSuite) {
suite.Require().NoError(suite.Runtime().RegisterController(&runtime.ExtensionServicesConfigFilesController{
suite.Require().NoError(suite.Runtime().RegisterController(&runtime.ExtensionServiceConfigFilesController{
ExtensionsConfigBaseDir: extensionsConfigDir,
}))
},
Expand All @@ -38,7 +38,7 @@ func TestExtensionServicesConfigFilesSuite(t *testing.T) {
})
}

func (suite *ExtensionServicesConfigFilesSuite) TestReconcileExtensionServicesConfigFiles() {
func (suite *ExtensionServiceConfigFilesSuite) TestReconcileExtensionServiceConfigFiles() {
for _, tt := range []struct {
extensionName string
configFiles []struct {
Expand Down Expand Up @@ -75,23 +75,23 @@ func (suite *ExtensionServicesConfigFilesSuite) TestReconcileExtensionServicesCo
},
},
} {
extensionServicesConfigFiles := runtimeres.NewExtensionServicesConfigSpec(runtimeres.NamespaceName, tt.extensionName)
extensionServicesConfigFiles.TypedSpec().Files = xslices.Map(tt.configFiles, func(config struct {
extensionServiceConfigFiles := runtimeres.NewExtensionServiceConfigSpec(runtimeres.NamespaceName, tt.extensionName)
extensionServiceConfigFiles.TypedSpec().Files = xslices.Map(tt.configFiles, func(config struct {
content string
mountPath string
},
) runtimeres.ExtensionServicesConfigFile {
return runtimeres.ExtensionServicesConfigFile{
) runtimeres.ExtensionServiceConfigFile {
return runtimeres.ExtensionServiceConfigFile{
Content: config.content,
MountPath: config.mountPath,
}
})

suite.Require().NoError(suite.State().Create(suite.Ctx(), extensionServicesConfigFiles))
suite.Require().NoError(suite.State().Create(suite.Ctx(), extensionServiceConfigFiles))

ctest.AssertResource(suite, tt.extensionName,
func(status *runtimeres.ExtensionServicesConfigStatus, asrt *assert.Assertions) {
asrt.Equal(extensionServicesConfigFiles.Metadata().Version().String(), status.TypedSpec().SpecVersion)
func(status *runtimeres.ExtensionServiceConfigStatus, asrt *assert.Assertions) {
asrt.Equal(extensionServiceConfigFiles.Metadata().Version().String(), status.TypedSpec().SpecVersion)
},
)

Expand All @@ -113,8 +113,8 @@ func (suite *ExtensionServicesConfigFilesSuite) TestReconcileExtensionServicesCo
suite.Assert().NoError(err)

// delete test-extension-b resource
suite.Assert().NoError(suite.State().Destroy(suite.Ctx(), runtimeres.NewExtensionServicesConfigSpec(runtimeres.NamespaceName, "test-extension-b").Metadata()))
ctest.AssertNoResource[*runtimeres.ExtensionServicesConfigStatus](suite, "test-extension-b")
suite.Assert().NoError(suite.State().Destroy(suite.Ctx(), runtimeres.NewExtensionServiceConfigSpec(runtimeres.NamespaceName, "test-extension-b").Metadata()))
ctest.AssertNoResource[*runtimeres.ExtensionServiceConfigStatus](suite, "test-extension-b")

suite.Assert().NoFileExists(filepath.Join(suite.extensionsConfigDir, "test", "testdata"))
suite.Assert().NoDirExists(filepath.Join(suite.extensionsConfigDir, "test"))
Expand Down
Loading

0 comments on commit 15e8bca

Please sign in to comment.