diff --git a/pkg/clouds/gcloud/postgres.go b/pkg/clouds/gcloud/postgres.go index a9faecc6..dff613d2 100644 --- a/pkg/clouds/gcloud/postgres.go +++ b/pkg/clouds/gcloud/postgres.go @@ -15,6 +15,16 @@ type PostgresGcpCloudsqlConfig struct { QueryInsightsEnabled *bool `json:"queryInsightsEnabled" yaml:"queryInsightsEnabled"` QueryStringLength *int `json:"queryStringLength" yaml:"queryStringLength"` UsersProvisionRuntime *ProvisionRuntimeConfig `json:"usersProvisionRuntime" yaml:"usersProvisionRuntime"` + // Backup configuration + BackupEnabled *bool `json:"backupEnabled,omitempty" yaml:"backupEnabled,omitempty"` + BackupStartTime *string `json:"backupStartTime,omitempty" yaml:"backupStartTime,omitempty"` + PointInTimeRecoveryEnabled *bool `json:"pointInTimeRecoveryEnabled,omitempty" yaml:"pointInTimeRecoveryEnabled,omitempty"` + TransactionLogRetentionDays *int `json:"transactionLogRetentionDays,omitempty" yaml:"transactionLogRetentionDays,omitempty"` + RetainedBackups *int `json:"retainedBackups,omitempty" yaml:"retainedBackups,omitempty"` + // High availability + AvailabilityType *string `json:"availabilityType,omitempty" yaml:"availabilityType,omitempty"` // ZONAL or REGIONAL + // SSL + RequireSsl *bool `json:"requireSsl,omitempty" yaml:"requireSsl,omitempty"` // Resource adoption fields Adopt bool `json:"adopt,omitempty" yaml:"adopt,omitempty"` InstanceName string `json:"instanceName,omitempty" yaml:"instanceName,omitempty"` diff --git a/pkg/clouds/pulumi/gcp/postgres.go b/pkg/clouds/pulumi/gcp/postgres.go index 150e30fb..82caa880 100644 --- a/pkg/clouds/pulumi/gcp/postgres.go +++ b/pkg/clouds/pulumi/gcp/postgres.go @@ -25,6 +25,12 @@ func Postgres(ctx *sdk.Context, stack api.Stack, input api.ResourceInput, params return nil, errors.Errorf("failed to convert postgresql config for %q", input.Descriptor.Type) } + if pgCfg.AvailabilityType != nil { + if *pgCfg.AvailabilityType != "ZONAL" && *pgCfg.AvailabilityType != "REGIONAL" { + return nil, errors.Errorf("availabilityType must be ZONAL or REGIONAL, got %q", *pgCfg.AvailabilityType) + } + } + // Handle resource adoption - exit early if adopting if pgCfg.Adopt { return AdoptPostgres(ctx, stack, input, params) @@ -72,6 +78,9 @@ func Postgres(ctx *sdk.Context, stack api.Stack, input api.ResourceInput, params lo.If(pgCfg.QueryStringLength != nil, lo.FromPtr(pgCfg.QueryStringLength)).Else(2048), ), }, + BackupConfiguration: backupConfiguration(pgCfg), + AvailabilityType: sdk.StringPtrFromPtr(pgCfg.AvailabilityType), + IpConfiguration: ipConfiguration(pgCfg), }, DeletionProtection: sdk.Bool(pgCfg.DeletionProtection != nil && *pgCfg.DeletionProtection), }, sdk.Provider(params.Provider)) @@ -82,6 +91,47 @@ func Postgres(ctx *sdk.Context, stack api.Stack, input api.ResourceInput, params return &api.ResourceOutput{Ref: pgInstance}, nil } +func backupConfiguration(pgCfg *gcloud.PostgresGcpCloudsqlConfig) *sql.DatabaseInstanceSettingsBackupConfigurationArgs { + if pgCfg.BackupEnabled == nil || !*pgCfg.BackupEnabled { + return nil + } + args := &sql.DatabaseInstanceSettingsBackupConfigurationArgs{ + Enabled: sdk.Bool(true), + PointInTimeRecoveryEnabled: sdk.Bool(pgCfg.PointInTimeRecoveryEnabled != nil && *pgCfg.PointInTimeRecoveryEnabled), + } + if pgCfg.BackupStartTime != nil { + args.StartTime = sdk.StringPtr(*pgCfg.BackupStartTime) + } + if pgCfg.TransactionLogRetentionDays != nil { + args.TransactionLogRetentionDays = sdk.Int(*pgCfg.TransactionLogRetentionDays) + } + if pgCfg.RetainedBackups != nil { + args.BackupRetentionSettings = &sql.DatabaseInstanceSettingsBackupConfigurationBackupRetentionSettingsArgs{ + RetainedBackups: sdk.Int(*pgCfg.RetainedBackups), + RetentionUnit: sdk.String("COUNT"), + } + } + return args +} + +// ipConfiguration returns IP settings only when requireSsl is explicitly set. +// When nil, returns nil so Pulumi leaves existing IP configuration unchanged. +// Uses SslMode (Pulumi GCP SDK v8) instead of deprecated RequireSsl. +// Preserves Ipv4Enabled=true to avoid wiping existing authorized networks. +func ipConfiguration(pgCfg *gcloud.PostgresGcpCloudsqlConfig) *sql.DatabaseInstanceSettingsIpConfigurationArgs { + if pgCfg.RequireSsl == nil { + return nil + } + sslMode := "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + if *pgCfg.RequireSsl { + sslMode = "ENCRYPTED_ONLY" + } + return &sql.DatabaseInstanceSettingsIpConfigurationArgs{ + Ipv4Enabled: sdk.Bool(true), + SslMode: sdk.String(sslMode), + } +} + func toPostgresRootPasswordExport(resName string) string { return fmt.Sprintf("%s-root-password", resName) }