diff --git a/go.mod b/go.mod index 4e664b2759..fa47cd1f87 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/magefile/mage v1.15.0 github.com/mholt/archiver/v3 v3.5.1 + github.com/mitchellh/mapstructure v1.5.0 github.com/olekukonko/tablewriter v0.0.5 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/shirou/gopsutil/v3 v3.24.3 @@ -119,7 +120,6 @@ require ( github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/term v0.5.0 // indirect diff --git a/internal/profile/_static/config.yml.example b/internal/profile/_static/config.yml.example index da3907f02a..c693c57fc7 100644 --- a/internal/profile/_static/config.yml.example +++ b/internal/profile/_static/config.yml.example @@ -18,3 +18,8 @@ # Flag to enable logstash in elastic-package stack profile config # stack.logstash_enabled: true +## Specify agent ports to publish +## port definition schema https://docs.docker.com/compose/compose-file/compose-file-v2/#ports +# stack.agent.ports: +# - 127.0.0.1:1514:1514/udp + diff --git a/internal/profile/_testdata/config.yml b/internal/profile/_testdata/config.yml index 9399fd359f..d116928f4d 100644 --- a/internal/profile/_testdata/config.yml +++ b/internal/profile/_testdata/config.yml @@ -18,3 +18,8 @@ other.float: 0.12345 # A bool. Will be parsed as string. other.bool: false + +other.array: + - "entry1" + - "entry2" + - "entry3" \ No newline at end of file diff --git a/internal/profile/config.go b/internal/profile/config.go index f049b4ee75..85ef1c8d29 100644 --- a/internal/profile/config.go +++ b/internal/profile/config.go @@ -10,6 +10,7 @@ import ( "os" "github.com/elastic/go-ucfg/yaml" + "github.com/mitchellh/mapstructure" "github.com/elastic/elastic-package/internal/common" ) @@ -48,3 +49,18 @@ func (c *config) get(name string) (string, bool) { return fmt.Sprintf("%v", v), true } } + +func (c *config) Decode(name string, out any) error { + v, err := c.settings.GetValue(name) + if err != nil { + if errors.Is(err, common.ErrKeyNotFound) { + return nil + } + return err + } + if err := mapstructure.Decode(v, out); err != nil { + return err + } + + return nil +} diff --git a/internal/profile/config_test.go b/internal/profile/config_test.go index 3fbcc61130..467fc8a5dd 100644 --- a/internal/profile/config_test.go +++ b/internal/profile/config_test.go @@ -75,3 +75,30 @@ func TestLoadProfileConfig(t *testing.T) { }) } } + +func TestConfigDecode(t *testing.T) { + cases := []struct { + name string + expected any + output any + found bool + }{ + { + name: "other.array", + expected: []string{"entry1", "entry2", "entry3"}, + output: []string{}, + found: true, + }, + } + + config, err := loadProfileConfig("_testdata/config.yml") + require.NoError(t, err) + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + err := config.Decode(c.name, &c.output) + require.NoError(t, err) + assert.Equal(t, c.expected, c.output) + }) + } +} diff --git a/internal/profile/profile.go b/internal/profile/profile.go index ba5d8ea9a4..c433ba0287 100644 --- a/internal/profile/profile.go +++ b/internal/profile/profile.go @@ -161,6 +161,10 @@ func (profile Profile) Config(name string, def string) string { return def } +func (profile *Profile) Decode(name string, dst any) error { + return profile.config.Decode(name, dst) +} + // RuntimeOverrides defines configuration overrides for the current session. func (profile *Profile) RuntimeOverrides(overrides map[string]string) { profile.overrides = overrides diff --git a/internal/stack/_static/docker-compose-stack.yml.tmpl b/internal/stack/_static/docker-compose-stack.yml.tmpl index 319e69a899..dfbe1ea324 100644 --- a/internal/stack/_static/docker-compose-stack.yml.tmpl +++ b/internal/stack/_static/docker-compose-stack.yml.tmpl @@ -141,6 +141,7 @@ services: env_file: "./elastic-agent.env" cap_drop: - ALL + ports: [{{ fact "agent_publish_ports" }}] volumes: - "../certs/ca-cert.pem:/etc/ssl/certs/elastic-package.pem" - type: bind diff --git a/internal/stack/resources.go b/internal/stack/resources.go index 441283f2d0..008c766e48 100644 --- a/internal/stack/resources.go +++ b/internal/stack/resources.go @@ -134,6 +134,11 @@ var ( func applyResources(profile *profile.Profile, stackVersion string) error { stackDir := filepath.Join(profile.ProfilePath, ProfileStackPath) + var agentPorts []string + if err := profile.Decode("stack.agent.ports", &agentPorts); err != nil { + return fmt.Errorf("failed to unmarshal stack.agent.ports: %w", err) + } + resourceManager := resource.NewManager() resourceManager.AddFacter(resource.StaticFacter{ "registry_base_image": PackageRegistryBaseImage, @@ -152,9 +157,12 @@ func applyResources(profile *profile.Profile, stackVersion string) error { "geoip_dir": profile.Config(configGeoIPDir, "./ingest-geoip"), "logstash_enabled": profile.Config(configLogstashEnabled, "false"), "self_monitor_enabled": profile.Config(configSelfMonitorEnabled, "false"), + "agent_publish_ports": strings.Join(agentPorts, ","), }) - os.MkdirAll(stackDir, 0755) + if err := os.MkdirAll(stackDir, 0755); err != nil { + return fmt.Errorf("failed to create stack directory: %w", err) + } resourceManager.RegisterProvider("file", &resource.FileProvider{ Prefix: stackDir, })