Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a7e2329
[#1587] Exclude a common part of CLI parser
fivitti Jan 2, 2025
ac04f65
[#1587] Working general CLI parser
fivitti Jan 3, 2025
ffd2cf4
[#1587] Fix the wrong argument
fivitti Jan 7, 2025
8808118
[#1587] Unify agent and server parsers
fivitti Jan 7, 2025
e301a43
[#1587] Verify the envvars
fivitti Jan 7, 2025
30c4d21
[#1587] Fix linter issues
fivitti Jan 7, 2025
c8ca1c5
[#1587] Verify system environment variables
fivitti Jan 7, 2025
81b857a
[#1587] Add unit tests
fivitti Jan 7, 2025
48add73
[#1587] Extend unit test
fivitti Jan 7, 2025
06ba0b6
[#1587] Fix unit tests
fivitti Jan 7, 2025
cfb6ec4
[#1587] Simplify utility
fivitti Jan 7, 2025
7a29eb8
[#1587] Fix linter issue
fivitti Jan 8, 2025
522be1b
[#1587] Remove redundant flags
fivitti Jan 8, 2025
c6657d4
[#1587] Add unit tests
fivitti Jan 8, 2025
bf98f00
[#1587] Add a Changelog entry
fivitti Jan 8, 2025
19b7c94
[#1587] Unify the CLI handling in the Stork tool
fivitti Jan 8, 2025
66db02f
[#1587] Move package
fivitti Jan 8, 2025
425910d
[#1587] Exclude app to a separate file
fivitti Jan 8, 2025
7b201bd
[#1587] Unexport structs
fivitti Jan 8, 2025
6569020
[#1587] Unify code-gen CLI
fivitti Jan 8, 2025
27c6b7c
[#1587] Remove unnecessary dependencies
fivitti Jan 8, 2025
185123d
[#1587] Rename structs
fivitti Jan 9, 2025
f1d16f2
[#1587] Add unit tests
fivitti Jan 9, 2025
60f2fe4
[#1587] Rephrase a sentence
fivitti Jan 9, 2025
1acfd8d
[#1587] Support hooks only for agent and server
fivitti Jan 9, 2025
9285a3c
[#1587] Add unit test
fivitti Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[#1587] Verify the envvars
  • Loading branch information
fivitti authored and tomaszmrugalski committed Jun 2, 2025
commit e301a436e0d7dec639c60e88113aeb175f662b81
40 changes: 40 additions & 0 deletions backend/appcfg/stork/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ func (p *CLIParser) bootstrap() (*HookDirectorySettings, GroupedHookCLIFlags, er
}
p.substitutePlaceholdersInGroup(group)

err = p.verifyEnvironmentFile(envFileSettings)
if err != nil {
return nil, nil, err
}

return hookDirectorySettings, allHookCLIFlags, nil
}

Expand Down Expand Up @@ -256,6 +261,41 @@ func (p *CLIParser) loadEnvironmentFile(envFileSettings *environmentFileSettings
return nil
}

// Verifies if all environment variables in the environment file are known.
// Returns an error if any of the environment variables is unknown.
func (p *CLIParser) verifyEnvironmentFile(envFileSettings *environmentFileSettings) error {
if !envFileSettings.UseEnvFile {
// Nothing to do.
return nil
}

// Load the environment file content.
entries, err := storkutil.LoadEnvironmentFile(envFileSettings.EnvFile)
if err != nil {
err = errors.WithMessagef(err, "invalid environment file: '%s'", envFileSettings.EnvFile)
return err
}

// Collect all known environment variables.
knownEnvironmentVariables := make(map[string]bool)
for _, group := range p.parser.Groups() {
for _, option := range group.Options() {
knownEnvironmentVariables[option.EnvKeyWithNamespace()] = true
}
}

// Check if all environment variables are known.
var errs []error
for _, entry := range entries {
if _, exist := knownEnvironmentVariables[entry.GetKey()]; !exist {
err = errors.Errorf("unknown environment variable: '%s'", entry.GetKey())
errs = append(errs, err)
}
}

return storkutil.CombineErrors("the environment file contains unknown environment variables", errs)
}

// Extracts the CLI flags from the hooks.
func (p *CLIParser) collectHookCLIFlags(hookDirectorySettings *HookDirectorySettings) (map[string]hooks.HookSettings, error) {
allCLIFlags := map[string]hooks.HookSettings{}
Expand Down
43 changes: 27 additions & 16 deletions backend/util/envfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ import (
)

// Stores key-value of the environment variable.
type keyValuePair struct {
key string
value string
type KeyValuePair [2]string

// Returns the key of the key-value pair.
func (p KeyValuePair) GetKey() string {
return p[0]
}

// Returns the value of the key-value pair.
func (p KeyValuePair) GetValue() string {
return p[1]
}

// Defines an interface that accepts the environment variables.
Expand All @@ -37,20 +44,20 @@ func (s *processEnvironmentVariableSetter) Set(key, value string) error {

// Loads all entries from the environment file into one or multiple setters.
func LoadEnvironmentFileToSetter(path string, setters ...EnvironmentVariableSetter) error {
data, err := loadEnvironmentFile(path)
data, err := LoadEnvironmentFile(path)
if err != nil {
return err
}

for _, pair := range data {
for _, setter := range setters {
err = setter.Set(pair.key, pair.value)
err = setter.Set(pair.GetKey(), pair.GetValue())
if err != nil {
err = errors.WithMessagef(
err,
"cannot set '%s=%s' environment variable",
pair.key,
pair.value,
pair.GetKey(),
pair.GetValue(),
)
return err
}
Expand All @@ -61,7 +68,7 @@ func LoadEnvironmentFileToSetter(path string, setters ...EnvironmentVariableSett
}

// Loads all entries from the environment file.
func loadEnvironmentFile(path string) ([]*keyValuePair, error) {
func LoadEnvironmentFile(path string) ([]KeyValuePair, error) {
file, err := os.Open(path)
if err != nil {
return nil, errors.Wrapf(err, "cannot open the '%s' environment file", path)
Expand All @@ -71,9 +78,8 @@ func loadEnvironmentFile(path string) ([]*keyValuePair, error) {
}

// Loads all entries from a given reader.
func loadEnvironmentEntries(reader io.Reader) ([]*keyValuePair, error) {
data := []*keyValuePair{}
dataIndex := map[string]*keyValuePair{}
func loadEnvironmentEntries(reader io.Reader) ([]KeyValuePair, error) {
dataIndex := map[string]string{}
scanner := bufio.NewScanner(reader)

lineIdx := 0
Expand All @@ -88,15 +94,20 @@ func loadEnvironmentEntries(reader io.Reader) ([]*keyValuePair, error) {
continue
}

if pair, ok := dataIndex[key]; ok {
pair.value = value
if _, ok := dataIndex[key]; ok {
// Duplicate key. Use the latest value.
dataIndex[key] = value
} else {
pair := &keyValuePair{key, value}
data = append(data, pair)
dataIndex[key] = pair
// New key.
dataIndex[key] = value
}
}

var data []KeyValuePair
for key, value := range dataIndex {
data = append(data, [2]string{key, value})
}

return data, nil
}

Expand Down
42 changes: 21 additions & 21 deletions backend/util/envfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestLoadMissingEnvironmentFile(t *testing.T) {
// Arrange & Act
sb := testutil.NewSandbox()
defer sb.Close()
data, err := loadEnvironmentFile(path.Join(sb.BasePath, "not-exists.env"))
data, err := LoadEnvironmentFile(path.Join(sb.BasePath, "not-exists.env"))

// Assert
require.Error(t, err)
Expand All @@ -34,8 +34,8 @@ func TestLoadSingleLineEnvironmentContent(t *testing.T) {
// Assert
require.NoError(t, err)
require.Len(t, data, 1)
require.EqualValues(t, "TEST_STORK_KEY", data[0].key)
require.EqualValues(t, "VALUE", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY", data[0].GetKey())
require.EqualValues(t, "VALUE", data[0].GetValue())
}

// Test that the multi-line environment file content is loaded properly.
Expand All @@ -51,12 +51,12 @@ func TestLoadMultiLineEnvironmentContent(t *testing.T) {
// Assert
require.NoError(t, err)
require.Len(t, data, 3)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].key)
require.EqualValues(t, "VALUE1", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY2", data[1].key)
require.EqualValues(t, "VALUE2", data[1].value)
require.EqualValues(t, "TEST_STORK_KEY3", data[2].key)
require.EqualValues(t, "VALUE3", data[2].value)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].GetKey())
require.EqualValues(t, "VALUE1", data[0].GetValue())
require.EqualValues(t, "TEST_STORK_KEY2", data[1].GetKey())
require.EqualValues(t, "VALUE2", data[1].GetValue())
require.EqualValues(t, "TEST_STORK_KEY3", data[2].GetKey())
require.EqualValues(t, "VALUE3", data[2].GetValue())
}

// Test that the duplicates in the content are overwritten properly.
Expand All @@ -72,8 +72,8 @@ func TestLoadEnvironmentContentWithDuplicates(t *testing.T) {
// Assert
require.NoError(t, err)
require.Len(t, data, 1)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].key)
require.EqualValues(t, "VALUE3", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].GetKey())
require.EqualValues(t, "VALUE3", data[0].GetValue())
}

// Test that the empty value in the environment file content is loaded properly.
Expand All @@ -87,8 +87,8 @@ func TestLoadEnvironmentContentWithEmptyValue(t *testing.T) {
// Assert
require.Len(t, data, 1)
require.NoError(t, err)
require.EqualValues(t, "TEST_STORK_KEY", data[0].key)
require.EqualValues(t, "", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY", data[0].GetKey())
require.EqualValues(t, "", data[0].GetValue())
}

// Test that the missing value separator in the environment file content
Expand Down Expand Up @@ -146,8 +146,8 @@ func TestLoadEnvironmentContentWithComments(t *testing.T) {
// Assert
require.NoError(t, err)
require.Len(t, data, 1)
require.EqualValues(t, "TEST_STORK_KEY2", data[0].key)
require.EqualValues(t, "VALUE2", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY2", data[0].GetKey())
require.EqualValues(t, "VALUE2", data[0].GetValue())
}

// Test that the empty lines are skipped.
Expand All @@ -162,10 +162,10 @@ func TestLoadEnvironmentContentWithEmptyLine(t *testing.T) {

// Assert
require.NoError(t, err)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].key)
require.EqualValues(t, "VALUE1", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY2", data[1].key)
require.EqualValues(t, "VALUE2", data[1].value)
require.EqualValues(t, "TEST_STORK_KEY1", data[0].GetKey())
require.EqualValues(t, "VALUE1", data[0].GetValue())
require.EqualValues(t, "TEST_STORK_KEY2", data[1].GetKey())
require.EqualValues(t, "VALUE2", data[1].GetValue())
require.Len(t, data, 2)
}

Expand All @@ -182,8 +182,8 @@ func TestLoadEnvironmentContentWithTrailingCharacters(t *testing.T) {
// Assert
require.NoError(t, err)
require.Len(t, data, 1)
require.EqualValues(t, "TEST_STORK_KEY2", data[0].key)
require.EqualValues(t, "VALUE2", data[0].value)
require.EqualValues(t, "TEST_STORK_KEY2", data[0].GetKey())
require.EqualValues(t, "VALUE2", data[0].GetValue())
}

type setterMock struct {
Expand Down