sourcegraph/cmd/server/shared/shared.go
Eric Fritz 71ef03a178
SQLite backend (#5332)
This replaces the original proof-of-concept backend that simply used the code from Microsoft's [vscode extension](https://github.com/microsoft/vscode-lsif-extension/tree/master/server). This held all LSIF dumps in memory, which was an untenable solution at scale.

The new server uses SQLite databases to store LSIF data for a repository and commit pair.
2019-09-13 14:42:49 -05:00

191 lines
6.6 KiB
Go

// Package shared provides the entrypoint to Sourcegraph's single docker
// image. It has functionality to setup the shared environment variables, as
// well as create the Procfile for goreman to run.
package shared
import (
"encoding/json"
"flag"
"log"
"os"
"path/filepath"
"strings"
"github.com/joho/godotenv"
"github.com/sourcegraph/sourcegraph/cmd/server/internal/goreman"
)
// FrontendInternalHost is the value of SRC_FRONTEND_INTERNAL.
const FrontendInternalHost = "127.0.0.1:3090"
// defaultEnv is environment variables that will be set if not already set.
var defaultEnv = map[string]string{
// Sourcegraph services running in this container
"SRC_GIT_SERVERS": "127.0.0.1:3178",
"SEARCHER_URL": "http://127.0.0.1:3181",
"REPO_UPDATER_URL": "http://127.0.0.1:3182",
"QUERY_RUNNER_URL": "http://127.0.0.1:3183",
"SRC_SYNTECT_SERVER": "http://127.0.0.1:9238",
"SYMBOLS_URL": "http://127.0.0.1:3184",
"REPLACER_URL": "http://127.0.0.1:3185",
"LSIF_SERVER_URL": "http://127.0.0.1:3186",
"SRC_HTTP_ADDR": ":8080",
"SRC_HTTPS_ADDR": ":8443",
"SRC_FRONTEND_INTERNAL": FrontendInternalHost,
"GITHUB_BASE_URL": "http://127.0.0.1:3180", // points to github-proxy
// Limit our cache size to 100GB, same as prod. We should probably update
// searcher/symbols to ensure this value isn't larger than the volume for
// CACHE_DIR.
"SEARCHER_CACHE_SIZE_MB": "50000",
"REPLACER_CACHE_SIZE_MB": "50000",
"SYMBOLS_CACHE_SIZE_MB": "50000",
// Used to differentiate between deployments on dev, Docker, and Kubernetes.
"DEPLOY_TYPE": "docker-container",
// enables the debug proxy (/-/debug)
"SRC_PROF_HTTP": "",
"LOGO": "t",
"SRC_LOG_LEVEL": "warn",
// TODO other bits
// * DEBUG LOG_REQUESTS https://github.com/sourcegraph/sourcegraph/issues/8458
}
// Set verbosity based on simple interpretation of env var to avoid external dependencies (such as
// on github.com/sourcegraph/sourcegraph/pkg/env).
var verbose = os.Getenv("SRC_LOG_LEVEL") == "dbug" || os.Getenv("SRC_LOG_LEVEL") == "info"
// Main is the main server command function which is shared between Sourcegraph
// server's open-source and enterprise variant.
func Main() {
flag.Parse()
log.SetFlags(0)
// Ensure CONFIG_DIR and DATA_DIR
// Load $CONFIG_DIR/env before we set any defaults
{
configDir := SetDefaultEnv("CONFIG_DIR", "/etc/sourcegraph")
err := os.MkdirAll(configDir, 0755)
if err != nil {
log.Fatalf("failed to ensure CONFIG_DIR exists: %s", err)
}
err = godotenv.Load(filepath.Join(configDir, "env"))
if err != nil && !os.IsNotExist(err) {
log.Fatalf("failed to load %s: %s", filepath.Join(configDir, "env"), err)
}
// Load the legacy config file if it exists.
//
// TODO(slimsag): Remove this code in the next significant version of
// Sourcegraph after 3.0.
configPath := os.Getenv("SOURCEGRAPH_CONFIG_FILE")
if configPath == "" {
configPath = filepath.Join(configDir, "sourcegraph-config.json")
}
_, err = os.Stat(configPath)
if err == nil {
if err := os.Setenv("SOURCEGRAPH_CONFIG_FILE", configPath); err != nil {
log.Fatal(err)
}
}
}
// Next persistence
{
SetDefaultEnv("SRC_REPOS_DIR", filepath.Join(DataDir, "repos"))
SetDefaultEnv("LSIF_STORAGE_ROOT", filepath.Join(DataDir, "lsif-storage"))
SetDefaultEnv("CACHE_DIR", filepath.Join(DataDir, "cache"))
}
// Special case some convenience environment variables
if redis, ok := os.LookupEnv("REDIS"); ok {
SetDefaultEnv("REDIS_ENDPOINT", redis)
}
data, err := json.MarshalIndent(SrcProfServices, "", " ")
if err != nil {
log.Println("Failed to marshal default SRC_PROF_SERVICES")
} else {
SetDefaultEnv("SRC_PROF_SERVICES", string(data))
}
for k, v := range defaultEnv {
SetDefaultEnv(k, v)
}
// Now we put things in the right place on the FS
if err := copySSH(); err != nil {
// TODO There are likely several cases where we don't need SSH
// working, we shouldn't prevent setup in those cases. The main one
// that comes to mind is an ORIGIN_MAP which creates https clone URLs.
log.Println("Failed to setup SSH authorization:", err)
log.Fatal("SSH authorization required for cloning from your codehost. Please see README.")
}
if err := copyNetrc(); err != nil {
log.Fatal("Failed to copy netrc:", err)
}
// TODO validate known_hosts contains all code hosts in config.
nginx, err := nginxProcFile()
if err != nil {
log.Fatal("Failed to setup nginx:", err)
}
procfile := []string{
nginx,
`frontend: env CONFIGURATION_MODE=server frontend`,
`gitserver: gitserver`,
`query-runner: query-runner`,
`symbols: symbols`,
`lsif-server: node /lsif/out/server.js`,
`management-console: management-console`,
`searcher: searcher`,
`github-proxy: github-proxy`,
`repo-updater: repo-updater`,
`syntect_server: sh -c 'env QUIET=true ROCKET_ENV=production ROCKET_PORT=9238 ROCKET_LIMITS='"'"'{json=10485760}'"'"' ROCKET_SECRET_KEY='"'"'SeerutKeyIsI7releuantAndknvsuZPluaseIgnorYA='"'"' ROCKET_KEEP_ALIVE=0 ROCKET_ADDRESS='"'"'"127.0.0.1"'"'"' syntect_server | grep -v "Rocket has launched" | grep -v "Warning: environment is"' | grep -v 'Configured for production'`,
`prometheus: prometheus --config.file=/sg_config_prometheus/prometheus.yml --storage.tsdb.path=/var/opt/sourcegraph/prometheus --web.console.libraries=/usr/share/prometheus/console_libraries --web.console.templates=/usr/share/prometheus/consoles >> /var/opt/sourcegraph/prometheus.log 2>&1`,
`grafana: env GF_AUTH_ANONYMOUS_ENABLED=true GF_AUTH_ANONYMOUS_ORG_NAME=Sourcegraph GF_AUTH_ANONYMOUS_ORG_ROLE=Editor GF_USERS_ALLOW_SIGN_UP=false GF_USERS_AUTO_ASSIGN_ORG=true GF_USERS_AUTO_ASSIGN_ORG_ROLE=Editor /usr/share/grafana/bin/grafana-server -config /sg_config_grafana/grafana.ini -homepath /usr/share/grafana >> /var/opt/sourcegraph/grafana.log 2>&1`,
}
procfile = append(procfile, ProcfileAdditions...)
redisStoreLine, err := maybeRedisStoreProcFile()
if err != nil {
log.Fatal(err)
}
if redisStoreLine != "" {
procfile = append(procfile, redisStoreLine)
}
redisCacheLine, err := maybeRedisCacheProcFile()
if err != nil {
log.Fatal(err)
}
if redisCacheLine != "" {
procfile = append(procfile, redisCacheLine)
}
if line, err := maybePostgresProcFile(); err != nil {
log.Fatal(err)
} else if line != "" {
procfile = append(procfile, line)
}
procfile = append(procfile, maybeZoektProcFile()...)
const goremanAddr = "127.0.0.1:5005"
if err := os.Setenv("GOREMAN_RPC_ADDR", goremanAddr); err != nil {
log.Fatal(err)
}
err = goreman.Start(goremanAddr, []byte(strings.Join(procfile, "\n")))
if err != nil {
log.Fatal(err)
}
}