Skip to content

Commit

Permalink
feat(config): support system extensions config file
Browse files Browse the repository at this point in the history
Signed-off-by: budimanjojo <budimanjojo@gmail.com>
  • Loading branch information
budimanjojo committed Apr 29, 2024
1 parent 45865fa commit 4b1e836
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 0 deletions.
7 changes: 7 additions & 0 deletions example/talconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ patches:
GRPC_GO_LOG_SEVERITY_LEVEL: error
nodes:
- hostname: kmaster1
extensionServices:
- name: nut-client
configFiles:
- content: MONITOR upsmonHost 1 remote pass password
mountPath: /usr/local/etc/nut/upsmon.conf
environment:
- UPS_NAME=ups
ingressFirewall:
defaultAction: block
rules:
Expand Down
8 changes: 8 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"github.com/siderolabs/image-factory/pkg/schematic"
"github.com/siderolabs/talos/pkg/machinery/config/types/network"
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime/extensions"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
)
Expand Down Expand Up @@ -54,6 +55,7 @@ type NodeConfigs struct {
Schematic *schematic.Schematic `yaml:"schematic,omitempty" jsonschema:"description=Talos image customization to be used in the installer image"`
MachineSpec MachineSpec `yaml:"machineSpec,omitempty" jsonschema:"description=Machine hardware specification"`
IngressFirewall *IngressFirewall `yaml:"ingressFirewall,omitempty" jsonschema:"description=Machine firewall specification"`
ExtensionServices []*ExtensionService `yaml:"extensionServices,omitempty" jsonschema:"description=Machine extension services specification"`
}

type ImageFactory struct {
Expand Down Expand Up @@ -81,3 +83,9 @@ type NetworkRule struct {
PortSelector network.RulePortSelector `yaml:"portSelector" jsonschema:"description=Ports and protocols on the host affected by the rule"`
Ingress network.IngressConfig `yaml:"ingress" jsonschema:"description=List of source subnets allowed to access the host ports/protocols"`
}

type ExtensionService struct {
Name string `yaml:"name" jsonschema:"description=Name of the extension service config"`
ConfigFiles []extensions.ConfigFile `yaml:"configFiles,omitempty" jsonschema:"description=The config files for the extension service"`
Environment []string `yaml:"environment,omitempty" jsonschema:"description=The environment for the extension service"`
}
9 changes: 9 additions & 0 deletions pkg/generate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func GenerateConfig(c *config.TalhelperConfig, dryRun bool, outDir, secretFile,
cfg = append(cfg, nc...)
}

if len(node.ExtensionServices) > 0 {
slog.Debug(fmt.Sprintf("generating machine extension service config for %s", node.Hostname))
ext, err := talos.GenerateExtensionServicesConfigBytes(node.ExtensionServices)
if err != nil {
return err
}
cfg = append(cfg, ext...)
}

if len(node.ExtraManifests) > 0 {
slog.Debug(fmt.Sprintf("generating extra manifests for %s", node.Hostname))
content, err := combineExtraManifests(node.ExtraManifests)
Expand Down
45 changes: 45 additions & 0 deletions pkg/talos/extensionserviceconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package talos

import (
"github.com/budimanjojo/talhelper/pkg/config"
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime/extensions"
)

func GenerateExtensionServicesConfigBytes(esCfgs []*config.ExtensionService) ([]byte, error) {
var result [][]byte

exts, err := GenerateNodeExtensionServiceConfig(esCfgs)
if err != nil {
return nil, err
}

for _, ext := range exts {
extByte, err := marshalYaml(ext)
if err != nil {
return nil, err
}

result = append(result, extByte)
}

return CombineYamlBytes(result), nil
}

func GenerateNodeExtensionServiceConfig(esCfgs []*config.ExtensionService) ([]*extensions.ServiceConfigV1Alpha1, error) {
var result []*extensions.ServiceConfigV1Alpha1

for _, v := range esCfgs {
esc := extensions.NewServicesConfigV1Alpha1()
esc.ServiceName = v.Name
esc.ServiceConfigFiles = v.ConfigFiles
esc.ServiceEnvironment = v.Environment

if _, err := esc.Validate(nil); err != nil {
return nil, err
}

result = append(result, esc)
}

return result, nil
}
63 changes: 63 additions & 0 deletions pkg/talos/extensionserviceconfig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package talos

import (
"testing"

"github.com/budimanjojo/talhelper/pkg/config"
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime/extensions"
"gopkg.in/yaml.v3"
)

func TestGenerateNodeExtensionServiceConfig(t *testing.T) {
data := []byte(`nodes:
- hostname: node1
extensionServices:
- name: nut-client
configFiles:
- content: MONITOR ${upsmonHost} 1 remote pass password
mountPath: /usr/local/etc/nut/upsmon.conf
environment:
- UPS_NAME=ups
- name: nut-client2
configFiles:
- content: hello
mountPath: /etc/hello
- content: hello2
mountPath: /etc/hello2`)

var m config.TalhelperConfig
if err := yaml.Unmarshal(data, &m); err != nil {
t.Fatal(err)
}

expectedExtension1Name := "nut-client"
expectedExtension1ConfigFiles := []extensions.ConfigFile{
{
ConfigFileContent: "MONITOR ${upsmonHost} 1 remote pass password",
ConfigFileMountPath: "/usr/local/etc/nut/upsmon.conf",
},
}
expectedExtension1Environment := []string{"UPS_NAME=ups"}
expectedExtension2Name := "nut-client2"
expectedExtension2ConfigFiles := []extensions.ConfigFile{
{
ConfigFileContent: "hello",
ConfigFileMountPath: "/etc/hello",
},
{
ConfigFileContent: "hello2",
ConfigFileMountPath: "/etc/hello2",
},
}

result, err := GenerateNodeExtensionServiceConfig(m.Nodes[0].ExtensionServices)
if err != nil {
t.Fatal(err)
}

compare(result[0].Name(), expectedExtension1Name, t)
compare(result[0].ServiceConfigFiles, expectedExtension1ConfigFiles, t)
compare(result[0].Environment(), expectedExtension1Environment, t)
compare(result[1].Name(), expectedExtension2Name, t)
compare(result[1].ServiceConfigFiles, expectedExtension2ConfigFiles, t)
}

0 comments on commit 4b1e836

Please sign in to comment.