Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feat_exit-code-event
Browse files Browse the repository at this point in the history
  • Loading branch information
varas committed Dec 11, 2020
2 parents 0716db7 + 1179761 commit 0a520b7
Show file tree
Hide file tree
Showing 18 changed files with 310 additions and 95 deletions.
2 changes: 1 addition & 1 deletion build/container/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ LABEL com.newrelic.nri-docker.version=$nri_docker_version \

RUN apk add --no-cache \
ntpsec=1.1.8-r0 \
curl=7.69.1-r1
curl=7.69.1-r2

COPY $nri_pkg_dir /
21 changes: 14 additions & 7 deletions cmd/newrelic-infra/newrelicinfra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@ import (
"github.com/newrelic/infrastructure-agent/pkg/log"
)

func TestLogRedirection(t *testing.T) {
func Test_configureLogRedirection(t *testing.T) {
// Given a new MemLogger with data
l := log.NewMemLogger(ioutil.Discard)
_, err := l.Write([]byte("example logs here"))
require.NoError(t, err)

// And a log file
logFile, err := ioutil.TempFile("", "newLogs.txt")
require.NoError(t, err)
logText := "example logs here"
_, _ = logFile.WriteString(logText)
cfg := &config.Config{

// When log redirection is configured to log file
assert.True(t, configureLogRedirection(&config.Config{
LogFile: logFile.Name(),
}
assert.True(t, configureLogRedirection(cfg, &log.MemLogger{}))
}, l))

// Then data previously stored in MemLogger gets written into log file
dat, err := ioutil.ReadFile(logFile.Name())
require.NoError(t, err)
assert.Equal(t, logText, string(dat))
assert.Equal(t, "example logs here", string(dat))
}
6 changes: 3 additions & 3 deletions internal/integrations/v4/integration/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ func (d *Definition) PluginID(integrationName string) ids.PluginID {
return ids.NewDefaultInventoryPluginID(d.Name)
}

func (d *Definition) Run(ctx context.Context, bind *databind.Values, pidC, exitCodeC chan<- int) ([]Output, error) {
func (d *Definition) Run(ctx context.Context, bindVals *databind.Values, pidC, exitCodeC chan<- int) ([]Output, error) {
logger := elog.WithField("integration_name", d.Name)
logger.Debug("Running task.")
// no discovery data: execute a single instance
if bind == nil {
if bindVals == nil {
logger.Debug("Running single instance.")
return []Output{{Receive: d.runnable.Execute(ctx, pidC, exitCodeC)}}, nil
}
Expand All @@ -92,7 +92,7 @@ func (d *Definition) Run(ctx context.Context, bind *databind.Values, pidC, exitC
if d.ConfigTemplate != nil {
onDemand = ignoreConfigPathVar(&foundConfigPath)
}
matches, err := databind.Replace(bind, discoveredConfig{
matches, err := databind.Replace(bindVals, discoveredConfig{
Executor: d.runnable.DeepClone(),
ConfigTemplate: d.ConfigTemplate,
}, databind.Provided(onDemand))
Expand Down
2 changes: 1 addition & 1 deletion internal/plugins/linux/hostinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func getKernelRelease() string {
return v
}

func getProductUuid(mode config.AgentMode) string {
func getProductUuid(mode string) string {
const unknownProductUUID = "unknown"

if mode == config.ModeUnprivileged {
Expand Down
55 changes: 43 additions & 12 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/newrelic/infrastructure-agent/pkg/databind/pkg/databind"
"gopkg.in/yaml.v2"
"math/rand"
"os"
Expand All @@ -28,15 +29,12 @@ import (
"github.com/newrelic/infrastructure-agent/pkg/log"
)

// AgentMode agent user run modes, possible values are: root, privileged or unprivileged
type AgentMode string

const (
envPrefix = "nria"
ModeUnknown = AgentMode("")
ModeRoot = AgentMode("root")
ModePrivileged = AgentMode("privileged")
ModeUnprivileged = AgentMode("unprivileged")
ModeUnknown = ""
ModeRoot = "root"
ModePrivileged = "privileged"
ModeUnprivileged = "unprivileged"
NonVerboseLogging = 0
VerboseLogging = 1
SmartVerboseLogging = 2
Expand All @@ -57,6 +55,9 @@ type IncludeMetricsMap map[string][]string
// Configuration structs
// Use the 'public' annotation to specify the visibility of the config option: false/obfuscate [default: true]
type Config struct {
// Databind provides varaiable (secrets, discovery) replacement capabilities for the configuration.
Databind databind.YAMLAgentConfig `yaml:",inline"`

// License specifies the license key for your New Relic account. The agent uses this key to associate your server's
// metrics with your New Relic account. This setting is created as part of the standard installation process.
// Default: ""
Expand Down Expand Up @@ -932,7 +933,7 @@ type Config struct {
// - If the user is other than `root` but the capabilities don't match the ones in the previous rule, then the mode is `unprivileged`.
// Default: Runtime value
// Public: No
RunMode AgentMode
RunMode string

// AgentUser The name of the user that's executing the agent process. This value is taken from the runtime
// environment and cannot be manually set. The default Linux installation uses by default the `root` account to run
Expand Down Expand Up @@ -1203,30 +1204,60 @@ func (c *Config) toLogInfo() (map[string]string, error) {
return result, nil
}

func LoadConfig(configFile string) (*Config, error) {
func LoadConfig(configFile string) (cfg *Config, err error) {
var filesToCheck []string
if configFile != "" {
filesToCheck = append(filesToCheck, configFile)
}
filesToCheck = append(filesToCheck, defaultConfigFiles...)

cfg := NewConfig()
cfg = NewConfig()
cfgMetadata, err := config_loader.LoadYamlConfig(cfg, filesToCheck...)
if err != nil {
return cfg, fmt.Errorf("Unable to parse configuration file %s: %s", configFile, err)
err = fmt.Errorf("unable to parse configuration file %s: %s", configFile, err)
return
}

// After the config file has loaded, override via any environment variables
configOverride(cfg)

sources, err := cfg.Databind.DataSources()
if err != nil {
return
}
//_, err = databind.Fetch(sources)
vals, err := databind.Fetch(sources)
if err != nil {
return
}
if vals.VarsLen() > 0 {
cfg.Databind = databind.YAMLAgentConfig{}
matches, errD := databind.Replace(&vals, cfg)
if errD != nil {
return
}

if len(matches) != 1 {
err = fmt.Errorf("unexpected config file variables replacement amount")
return
}
transformed := matches[0]
replacedCfg, ok := transformed.Variables.(*Config)
if !ok {
err = fmt.Errorf("unexpected config file variables replacement type")
return
}
cfg = replacedCfg
}

cfg.RunMode, cfg.AgentUser, cfg.ExecutablePath = runtimeValues()

// Move any other post processing steps that clean up or announce settings to be
// after both config file and env variable processing is complete. Need to review each of the items
// above and place each one at the bottom of this ordering
err = NormalizeConfig(cfg, *cfgMetadata)

return cfg, err
return
}

// NewConfig returns the default Config.
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const (
defaultConnectEnabled = true
)

func runtimeValues() (userMode AgentMode, agentUser, executablePath string) {
func runtimeValues() (userMode, agentUser, executablePath string) {
return ModeRoot, "", ""
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func hostOverride(cfg *Config) {
// - root if the running user is root
// - privileged if the binary has capabilities: `cap_dac_read_search` and `cap_sys_ptrace`.
// - unprivileged otherwise
func runtimeValues() (agentMode AgentMode, agentUser, executablePath string) {
func runtimeValues() (agentMode, agentUser, executablePath string) {
agentMode = ModeUnknown

usr, err := user.Current()
Expand Down
38 changes: 38 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/newrelic/infrastructure-agent/pkg/helpers"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
. "gopkg.in/check.v1"
)

Expand Down Expand Up @@ -586,3 +587,40 @@ func Test_ParseIncludeMatchingRule_EnvVar(t *testing.T) {
expected := IncludeMetricsMap{"process.name": []string{"regex \"kube*\""}}
assert.True(t, reflect.DeepEqual(cfg.IncludeMetricsMatchers, expected))
}

func TestLoadYamlConfig_withDatabindVariables(t *testing.T) {
yamlData := []byte(`
variables:
var1:
test:
value: "10.0.2.2:8888"
staging: true
license_key: "xxx"
proxy: ${var1}
`)

tmp, err := createTestFile(yamlData)
require.NoError(t, err)
defer os.Remove(tmp.Name())

cfg, err := LoadConfig(tmp.Name())

require.NoError(t, err)

assert.True(t, cfg.Staging)
assert.Equal(t, "xxx", cfg.License)
assert.Equal(t, "10.0.2.2:8888", cfg.Proxy)
}

func createTestFile(data []byte) (*os.File, error) {
tmp, err := ioutil.TempFile("", "loadconfig")
if err != nil {
return nil, err
}
_, err = tmp.Write(data)
if err != nil {
return nil, err
}
tmp.Close()
return tmp, nil
}
2 changes: 1 addition & 1 deletion pkg/config/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func init() {
defaultFluentBitNRLib = "out_newrelic.dll"
}

func runtimeValues() (userMode AgentMode, agentUser, executablePath string) {
func runtimeValues() (userMode, agentUser, executablePath string) {
userMode = ModeRoot

usr, err := user.Current()
Expand Down
47 changes: 47 additions & 0 deletions pkg/config/loader/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
package config_loader

import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strconv"
"strings"

"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -38,6 +42,11 @@ func LoadYamlConfig(configObject interface{}, configFilePaths ...string) (*YAMLM
return nil, err
}

rawConfig, err = ExpandEnvVars(rawConfig)
if err != nil {
return nil, err
}

return ParseConfig(rawConfig, configObject)
}
}
Expand Down Expand Up @@ -76,3 +85,41 @@ func fileExists(filename string) bool {
}
return true
}

func ExpandEnvVars(content []byte) ([]byte, error) {
r := regexp.MustCompile(`({{ *\w+.*?}})`)
matches := r.FindAllIndex(content, -1)

if len(matches) == 0 {
return content, nil
}

var newContent []byte
var lastReplacement int
for _, idx := range matches {
evStart := idx[0] + 2 // drop {{
evEnd := idx[1] - 2 // drop }}
if len(content) < evStart || len(content) < evEnd {
return content, fmt.Errorf("cannot replace configuration environment variables")
}

evName := strings.TrimSpace(string(content[evStart:evEnd]))
if evVal, exist := os.LookupEnv(evName); exist {
// quote non numerics
if _, err := strconv.ParseFloat(evVal, 64); err != nil {
evVal = fmt.Sprintf(`"%s"`, evVal)
}
newContent = append(newContent, content[lastReplacement:idx[0]]...)
newContent = append(newContent, []byte(evVal)...)
lastReplacement = idx[1]
} else {
return nil, fmt.Errorf("cannot replace configuration environment variables, missing env-var: %s", evName)
}
}

if lastReplacement != len(content) {
newContent = append(newContent, content[lastReplacement:]...)
}

return newContent, nil
}
Loading

0 comments on commit 0a520b7

Please sign in to comment.