Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
4 changes: 4 additions & 0 deletions internal/config/appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ type AppConfig struct {
RunLogRetentionDays int `json:"run_log_retention_days"`
RunRetentionEnabled bool `json:"run_retention_enabled"`
RunRetentionDays int `json:"run_retention_days"`
// DefaultTags are org-wide default tags merged beneath each pack's own
// default_tags parameter when pack configs are built from the DB.
DefaultTags map[string]string `json:"default_tags"`
}

// DefaultAppConfig returns the default values used when no row exists for
Expand All @@ -29,5 +32,6 @@ func DefaultAppConfig() AppConfig {
RunLogRetentionDays: 7,
RunRetentionEnabled: false,
RunRetentionDays: 30,
DefaultTags: map[string]string{},
}
}
1 change: 1 addition & 0 deletions internal/config/appconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ func TestDefaultAppConfig(t *testing.T) {
RunLogRetentionDays: 7,
RunRetentionEnabled: false,
RunRetentionDays: 30,
DefaultTags: map[string]string{},
}, DefaultAppConfig())
}
7 changes: 7 additions & 0 deletions internal/db/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ func parseAppConfig(all map[string]json.RawMessage) config.AppConfig {
cfg.RunRetentionDays = n
}
}
if v, ok := all["default_tags"]; ok {
var m map[string]string
if err := json.Unmarshal(v, &m); err == nil && m != nil {
cfg.DefaultTags = m
}
}

return cfg
}
Expand All @@ -142,6 +148,7 @@ func appConfigKVs(c config.AppConfig) []appConfigKV {
{"run_log_retention_days", c.RunLogRetentionDays},
{"run_retention_enabled", c.RunRetentionEnabled},
{"run_retention_days", c.RunRetentionDays},
{"default_tags", c.DefaultTags},
}
}

Expand Down
8 changes: 7 additions & 1 deletion internal/db/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestParseAppConfig_InvalidJSONKeepsDefault(t *testing.T) {
"terraform_version": json.RawMessage(`123`),
"pack_logs_enabled": json.RawMessage(`"yes"`),
"ssh_logging_enabled": json.RawMessage(`{bad json`),
"default_tags": json.RawMessage(`"owner=secops"`),
})
assert.Equal(t, config.DefaultAppConfig(), got)
}
Expand All @@ -55,6 +56,7 @@ func TestParseAppConfig_AllSet(t *testing.T) {
"run_log_retention_days": json.RawMessage(`14`),
"run_retention_enabled": json.RawMessage(`true`),
"run_retention_days": json.RawMessage(`90`),
"default_tags": json.RawMessage(`{"owner":"secops"}`),
})
assert.Equal(t, config.AppConfig{
Parallelism: 12,
Expand All @@ -65,6 +67,7 @@ func TestParseAppConfig_AllSet(t *testing.T) {
RunLogRetentionDays: 14,
RunRetentionEnabled: true,
RunRetentionDays: 90,
DefaultTags: map[string]string{"owner": "secops"},
}, got)
}

Expand Down Expand Up @@ -94,6 +97,7 @@ func TestAppConfigKVs_MarshalsToExpectedJSON(t *testing.T) {
RunLogRetentionDays: 7,
RunRetentionEnabled: false,
RunRetentionDays: 30,
DefaultTags: map[string]string{"owner": "secops"},
}

want := map[string]string{
Expand All @@ -105,6 +109,7 @@ func TestAppConfigKVs_MarshalsToExpectedJSON(t *testing.T) {
"run_log_retention_days": `7`,
"run_retention_enabled": `false`,
"run_retention_days": `30`,
"default_tags": `{"owner":"secops"}`,
}

kvs := appConfigKVs(c)
Expand All @@ -129,6 +134,7 @@ func TestFakeConfigStore_UpdateGetAppConfigRoundtrip(t *testing.T) {
RunLogRetentionDays: 14,
RunRetentionEnabled: true,
RunRetentionDays: 90,
DefaultTags: map[string]string{"owner": "secops", "simulated": "true"},
}
require.NoError(t, f.UpdateAppConfig(ctx, want))

Expand All @@ -139,7 +145,7 @@ func TestFakeConfigStore_UpdateGetAppConfigRoundtrip(t *testing.T) {
assert.Equal(t, []string{
"parallelism", "terraform_version", "pack_logs_enabled", "ssh_logging_enabled",
"run_log_retention_enabled", "run_log_retention_days",
"run_retention_enabled", "run_retention_days",
"run_retention_enabled", "run_retention_days", "default_tags",
}, f.sets)
}

Expand Down
1 change: 1 addition & 0 deletions internal/db/migrations/018_default_tags_appconfig.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM app_config WHERE key = 'default_tags';
5 changes: 5 additions & 0 deletions internal/db/migrations/018_default_tags_appconfig.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Backfill app_config with the org-wide default_tags key.
-- Idempotent — only inserts if the key is missing. Aligned with DefaultAppConfig().
INSERT INTO app_config (key, value) VALUES
('default_tags', '{}'::jsonb)
ON CONFLICT (key) DO NOTHING;
17 changes: 17 additions & 0 deletions internal/detonators/simrun_detonator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,23 @@ func TestTerraformEnvVars_MapValueJSONEncoded(t *testing.T) {
}
}

// The org-wide default tags merge (web.loadPacksFromDB) stores default_tags
// as map[string]string; it must reach terraform identically to the
// map[string]any a pack stores on its own.
func TestTerraformEnvVars_MergedStringMapJSONEncoded(t *testing.T) {
d := &SimrunDetonator{
packConfig: config.PackConfig{
Parameters: map[string]any{
"default_tags": map[string]string{"owner": "secops"},
},
},
}
env := d.terraformEnvVars("exec-1")
if got := env["TF_VAR_default_tags"]; got != `{"owner":"secops"}` {
t.Errorf("TF_VAR_default_tags = %q, want JSON-encoded object", got)
}
}

func TestFormatTFVar(t *testing.T) {
tests := []struct {
in any
Expand Down
Loading