Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 2 additions & 2 deletions cmd/settings/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,13 @@ func buildEnvVar(extraEnvVar []corev1.EnvVar, config *config.Config) []corev1.En
commonVar := []corev1.EnvVar{
{Name: "BACKUP_CONFIGURATION_BUCKET_NAME", Value: config.Settings.Bucket},
{Name: "BACKUP_CONFIGURATION_S3_PREFIX", Value: config.Settings.S3Prefix},
{Name: "BACKUP_CONFIGURATION_STACKPACKS_S3_PREFIX", Value: config.Settings.StackpacksS3Prefix},
{Name: "MINIO_ENDPOINT", Value: fmt.Sprintf("%s:%d", storageService.Name, storageService.Port)},
{Name: "STACKSTATE_BASE_URL", Value: config.GetBaseURL()},
{Name: "RECEIVER_BASE_URL", Value: config.GetReceiverBaseURL()},
{Name: "PLATFORM_VERSION", Value: config.GetPlatformVersion()},
{Name: "ZOOKEEPER_QUORUM", Value: config.Settings.Restore.ZookeeperQuorum},
{Name: "BACKUP_CONFIGURATION_UPLOAD_REMOTE", Value: strconv.FormatBool(config.GlobalBackupEnabled())},
{Name: "SKIP_STACKPACKS", Value: strconv.FormatBool(skipStackpacks)},
{Name: "SKIP_STACKPACKS", Value: strconv.FormatBool(skipStackpacks || config.Stackpacks == nil)},
}
if fromPVC {
// Force PVC mode in the shell script, suppress local bucket
Expand All @@ -214,6 +213,7 @@ func buildEnvVar(extraEnvVar []corev1.EnvVar, config *config.Config) []corev1.En
}
if config.Stackpacks != nil {
commonVar = append(commonVar, corev1.EnvVar{Name: "CONFIG_FORCE_stackstate_stackPacks_localStackPacksUri", Value: config.Stackpacks.LocalStackPacksURI})
commonVar = append(commonVar, corev1.EnvVar{Name: "BACKUP_CONFIGURATION_STACKPACKS_DIR", Value: config.Stackpacks.BackupDirectory})
}
commonVar = append(commonVar, extraEnvVar...)
return commonVar
Expand Down
72 changes: 72 additions & 0 deletions cmd/settings/restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,78 @@ import (
"github.com/stretchr/testify/assert"
)

func TestBuildEnvVar_SkipStackpacksWhenMissing(t *testing.T) {
tests := []struct {
name string
stackpacks *config.StackpacksConfig
skipStackpacksFlag bool
expectedValue string
}{
{
name: "stackpacks nil and flag false",
stackpacks: nil,
skipStackpacksFlag: false,
expectedValue: "true",
},
{
name: "stackpacks nil and flag true",
stackpacks: nil,
skipStackpacksFlag: true,
expectedValue: "true",
},
{
name: "stackpacks present and flag false",
stackpacks: &config.StackpacksConfig{
LocalStackPacksURI: "/var/stackpacks_local",
BackupDirectory: "stackpacks/",
},
skipStackpacksFlag: false,
expectedValue: "false",
},
{
name: "stackpacks present and flag true",
stackpacks: &config.StackpacksConfig{
LocalStackPacksURI: "/var/stackpacks_local",
BackupDirectory: "stackpacks/",
},
skipStackpacksFlag: true,
expectedValue: "true",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set the package-level flags
skipStackpacks = tt.skipStackpacksFlag
fromPVC = false

cfg := &config.Config{
Stackpacks: tt.stackpacks,
Storage: config.StorageConfig{
GlobalBackupEnabled: true,
Service: config.ServiceConfig{Name: "storage", Port: 9000},
},
Settings: config.SettingsConfig{
Bucket: "settings-backup",
Restore: config.SettingsRestoreConfig{
ZookeeperQuorum: "zk:2181",
},
},
}
envVars := buildEnvVar(nil, cfg)

var skipValue string
for _, env := range envVars {
if env.Name == "SKIP_STACKPACKS" {
skipValue = env.Value
break
}
}
assert.Equal(t, tt.expectedValue, skipValue)
})
}
}

func TestBuildVolumeMounts_StackpacksLocalFileURI(t *testing.T) {
tests := []struct {
name string
Expand Down
4 changes: 2 additions & 2 deletions cmd/stackgraph/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,17 +278,17 @@ func buildRestoreEnvVars(backupFile string, config *config.Config) []corev1.EnvV
{Name: "FORCE_DELETE", Value: purgeStackgraphDataFlag},
{Name: "BACKUP_STACKGRAPH_BUCKET_NAME", Value: config.Stackgraph.Bucket},
{Name: "BACKUP_STACKGRAPH_S3_PREFIX", Value: config.Stackgraph.S3Prefix},
{Name: "BACKUP_STACKGRAPH_STACKPACKS_S3_PREFIX", Value: config.Stackgraph.StackpacksS3Prefix},
{Name: "BACKUP_STACKGRAPH_MULTIPART_ARCHIVE", Value: strconv.FormatBool(config.Stackgraph.MultipartArchive)},
{Name: "MINIO_ENDPOINT", Value: fmt.Sprintf("%s:%d", storageService.Name, storageService.Port)},
{Name: "STACKSTATE_BASE_URL", Value: config.GetBaseURL()},
{Name: "RECEIVER_BASE_URL", Value: config.GetReceiverBaseURL()},
{Name: "PLATFORM_VERSION", Value: config.GetPlatformVersion()},
{Name: "ZOOKEEPER_QUORUM", Value: config.Stackgraph.Restore.ZookeeperQuorum},
{Name: "SKIP_STACKPACKS", Value: strconv.FormatBool(skipStackpacks)},
{Name: "SKIP_STACKPACKS", Value: strconv.FormatBool(skipStackpacks || config.Stackpacks == nil)},
}
if config.Stackpacks != nil {
env = append(env, corev1.EnvVar{Name: "CONFIG_FORCE_stackstate_stackPacks_localStackPacksUri", Value: config.Stackpacks.LocalStackPacksURI})
env = append(env, corev1.EnvVar{Name: "BACKUP_STACKGRAPH_STACKPACKS_DIR", Value: config.Stackpacks.BackupDirectory})
}
return env
}
Expand Down
64 changes: 64 additions & 0 deletions cmd/stackgraph/restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,70 @@ import (
"github.com/stretchr/testify/assert"
)

func TestBuildRestoreEnvVars_SkipStackpacksWhenMissing(t *testing.T) {
tests := []struct {
name string
stackpacks *config.StackpacksConfig
skipStackpacksFlag bool
expectedValue string
}{
{
name: "stackpacks nil and flag false",
stackpacks: nil,
skipStackpacksFlag: false,
expectedValue: "true",
},
{
name: "stackpacks nil and flag true",
stackpacks: nil,
skipStackpacksFlag: true,
expectedValue: "true",
},
{
name: "stackpacks present and flag false",
stackpacks: &config.StackpacksConfig{
LocalStackPacksURI: "/var/stackpacks_local",
BackupDirectory: "stackpacks/",
},
skipStackpacksFlag: false,
expectedValue: "false",
},
{
name: "stackpacks present and flag true",
stackpacks: &config.StackpacksConfig{
LocalStackPacksURI: "/var/stackpacks_local",
BackupDirectory: "stackpacks/",
},
skipStackpacksFlag: true,
expectedValue: "true",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set the package-level flag
skipStackpacks = tt.skipStackpacksFlag

cfg := &config.Config{
Stackpacks: tt.stackpacks,
Storage: config.StorageConfig{
Service: config.ServiceConfig{Name: "storage", Port: 9000},
},
}
envVars := buildRestoreEnvVars("backup.graph", cfg)

var skipValue string
for _, env := range envVars {
if env.Name == "SKIP_STACKPACKS" {
skipValue = env.Value
break
}
}
assert.Equal(t, tt.expectedValue, skipValue)
})
}
}

func TestBuildRestoreVolumeMounts_StackpacksLocalFileURI(t *testing.T) {
tests := []struct {
name string
Expand Down
19 changes: 9 additions & 10 deletions internal/foundation/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type StackpacksConfig struct {
PlatformVersion string `yaml:"platformVersion"`
LocalStackPacksURI string `yaml:"localStackPacksUri" validate:"required"`
PVC string `yaml:"pvc"`
BackupDirectory string `yaml:"backupDir" validate:"required"`
}

// GetBaseURL returns the StackState base URL, preferring the top-level stackpacks section
Expand Down Expand Up @@ -175,11 +176,10 @@ type StorageConfig struct {

// StackgraphConfig holds Stackgraph backup-specific configuration
type StackgraphConfig struct {
Bucket string `yaml:"bucket" validate:"required"`
S3Prefix string `yaml:"s3Prefix"`
StackpacksS3Prefix string `yaml:"stackpacksS3Prefix"`
MultipartArchive bool `yaml:"multipartArchive" validate:"boolean"`
Restore StackgraphRestoreConfig `yaml:"restore" validate:"required"`
Bucket string `yaml:"bucket" validate:"required"`
S3Prefix string `yaml:"s3Prefix"`
MultipartArchive bool `yaml:"multipartArchive" validate:"boolean"`
Restore StackgraphRestoreConfig `yaml:"restore" validate:"required"`
}

type VictoriaMetricsConfig struct {
Expand Down Expand Up @@ -210,11 +210,10 @@ type StackgraphRestoreConfig struct {
}

type SettingsConfig struct {
Bucket string `yaml:"bucket" validate:"required"`
S3Prefix string `yaml:"s3Prefix"`
StackpacksS3Prefix string `yaml:"stackpacksS3Prefix"`
LocalBucket string `yaml:"localBucket"`
Restore SettingsRestoreConfig `yaml:"restore" validate:"required"`
Bucket string `yaml:"bucket" validate:"required"`
S3Prefix string `yaml:"s3Prefix"`
LocalBucket string `yaml:"localBucket"`
Restore SettingsRestoreConfig `yaml:"restore" validate:"required"`
}

type SettingsRestoreConfig struct {
Expand Down
33 changes: 33 additions & 0 deletions internal/foundation/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,39 @@ func TestLoadConfig_Storage_WithSecretOverride(t *testing.T) {
assert.Equal(t, "secret-storage-secret-key", config.GetStorageSecretKey())
}

func TestLoadConfig_MissingStackpacksSection(t *testing.T) {
fakeClient := fake.NewClientset()
validConfigYAML := loadTestData(t, "validStorageConfigMapNoStackpacks.yaml")

// Create ConfigMap without stackpacks section
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "backup-config",
Namespace: "test-ns",
},
Data: map[string]string{
"config": validConfigYAML,
},
}
_, err := fakeClient.CoreV1().ConfigMaps("test-ns").Create(
context.Background(), cm, metav1.CreateOptions{},
)
require.NoError(t, err)

// Load config
config, err := LoadConfig(fakeClient, "test-ns", "backup-config", "")

// Assertions
require.NoError(t, err)
assert.NotNil(t, config)
// When stackpacks section is missing, Stackpacks should be nil
assert.Nil(t, config.Stackpacks)
// baseUrl/receiverBaseUrl/platformVersion should fall back to settings.restore values
assert.Equal(t, "http://suse-observability-server:7070", config.GetBaseURL())
assert.Equal(t, "http://suse-observability-receiver:7077", config.GetReceiverBaseURL())
assert.Equal(t, "5.2.0", config.GetPlatformVersion())
}

func TestLoadConfig_ConfigMapNotFound(t *testing.T) {
fakeClient := fake.NewClientset()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ stackpacks:
receiverBaseUrl: "http://suse-observability-receiver:7077"
platformVersion: "5.2.0"
localStackPacksUri: "/var/stackpacks_local"
backupDir: stackpacks/

# Minio configuration for S3-compatible storage
minio:
Expand All @@ -84,7 +85,6 @@ stackgraph:
# S3 prefix path for backups
s3Prefix: ""
# S3 prefix path for stackpacks backups
stackpacksS3Prefix: "stackpacks/"
# Archive split to multiple parts
multipartArchive: true
# Restore configuration
Expand Down Expand Up @@ -148,7 +148,6 @@ victoriaMetrics:
settings:
bucket: sts-settings-backup
s3Prefix: ""
stackpacksS3Prefix: "stackpacks/"
restore:
scaleDownLabelSelector: "observability.suse.com/scalable-during-settings-restore=true"
loggingConfigConfigMap: suse-observability-logging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ stackpacks:
receiverBaseUrl: "http://suse-observability-receiver:7077"
platformVersion: "5.2.0"
localStackPacksUri: "/var/stackpacks_local"
backupDir: "stackpacks/"

# Minio configuration for S3-compatible storage
minio:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ stackpacks:
receiverBaseUrl: "http://suse-observability-receiver:7077"
platformVersion: "5.2.0"
localStackPacksUri: "/var/stackpacks_local"
backupDir: "stackpacks/"

# Storage configuration for S3-compatible storage (new mode, replaces Minio)
storage:
Expand Down
Loading
Loading