-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.go
140 lines (120 loc) · 4.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"fmt"
"os"
"os/signal"
"registry-backend/config"
"registry-backend/ent"
"registry-backend/ent/migrate"
drip_logging "registry-backend/logging"
"registry-backend/server"
"syscall"
"github.com/rs/zerolog/log"
_ "github.com/lib/pq"
)
// validateEnvVars ensures all required environment variables are set based on the environment.
func validateEnvVars(env string) {
// Variables mandatory for all environments
mandatoryVars := []string{
"DB_CONNECTION_STRING",
"PROJECT_ID",
"DRIP_ENV",
"JWT_SECRET",
}
// TODO: Add staging specific variables
// Additional variables mandatory for production and staging
prodVars := []string{
"CLOUD_STORAGE_BUCKET_NAME",
"SLACK_REGISTRY_CHANNEL_WEBHOOK",
"SECRET_SCANNER_URL",
"SECURITY_COUNCIL_DISCORD_WEBHOOK",
"ALGOLIA_APP_ID",
"ALGOLIA_API_KEY",
"ID_TOKEN_AUDIENCE",
"PUBSUB_TOPIC",
}
// Add production specific variables
if env == "prod" {
mandatoryVars = append(mandatoryVars, prodVars...)
}
// Validate that all mandatory environment variables are set
var missingVars []string
for _, key := range mandatoryVars {
if os.Getenv(key) == "" {
missingVars = append(missingVars, key)
}
}
// Log and terminate if mandatory variables are missing
if len(missingVars) > 0 {
log.Fatal().Msgf("Missing mandatory environment variables for '%s': %v", env, missingVars)
}
}
func main() {
// Retrieve the current environment
dripEnv := os.Getenv("DRIP_ENV")
if dripEnv == "" {
log.Fatal().Msg("Environment variable DRIP_ENV is not set.")
}
// Validate environment variables based on the current environment
validateEnvVars(dripEnv)
// Set global log level based on the LOG_LEVEL environment variable
drip_logging.SetGlobalLogLevel(os.Getenv("LOG_LEVEL"))
// Retrieve the database connection string
connectionString := os.Getenv("DB_CONNECTION_STRING")
// Build the application configuration
appConfig := config.Config{
ProjectID: os.Getenv("PROJECT_ID"),
DripEnv: dripEnv,
SlackRegistryChannelWebhook: os.Getenv("SLACK_REGISTRY_CHANNEL_WEBHOOK"),
JWTSecret: os.Getenv("JWT_SECRET"),
SecretScannerURL: os.Getenv("SECRET_SCANNER_URL"),
DiscordSecurityChannelWebhook: os.Getenv("SECURITY_COUNCIL_DISCORD_WEBHOOK"),
DiscordSecurityPrivateChannelWebhook: os.Getenv("SECURITY_COUNCIL_DISCORD_PRIVATE_WEBHOOK"),
AlgoliaAppID: os.Getenv("ALGOLIA_APP_ID"),
AlgoliaAPIKey: os.Getenv("ALGOLIA_API_KEY"),
IDTokenAudience: os.Getenv("ID_TOKEN_AUDIENCE"),
CloudStorageBucketName: os.Getenv("CLOUD_STORAGE_BUCKET_NAME"),
PubSubTopic: os.Getenv("PUBSUB_TOPIC"),
NewRelicLicenseKey: os.Getenv("NEW_RELIC_LICENSE_KEY"),
}
// Construct the database connection string
var dsn string
if dripEnv == "localdev" {
// For local development, disable SSL for easier setup
dsn = fmt.Sprintf("%s sslmode=disable", connectionString)
} else {
// Use the connection string as-is for non-development environments
dsn = connectionString
}
// Initialize the database client
client, err := ent.Open("postgres", dsn)
if err != nil {
log.Fatal().Err(err).Msg("Failed to establish a connection to the PostgreSQL database.")
}
defer client.Close() // Ensure the database client is closed when the application exits
// Run database migrations in local development to keep the schema up to date
if dripEnv == "localdev" {
log.Info().Msg("Running migrations for local development.")
if err := client.Schema.Create(context.Background(),
migrate.WithDropIndex(true), migrate.WithDropColumn(true)); err != nil {
log.Fatal().Err(err).Msg("Failed to create schema resources during migration.")
}
}
// Handle graceful shutdown
go func() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
log.Info().Msg("Shutting down server gracefully.")
client.Close()
os.Exit(0)
}()
// Initialize and start the server
registryServer, err := server.NewServer(client, &appConfig)
if err != nil {
log.Fatal().Err(err).Msg("Failed to initialize the server.")
}
log.Info().Msg("Starting the server.")
log.Fatal().Err(registryServer.Start()).Msg("Server has stopped unexpectedly.")
}