mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 12:51:55 +00:00
enterprise-portal: initialize service with dotcom DB connection (#62525)
Closes https://linear.app/sourcegraph/issue/CORE-96 - this scaffolds an initial Enterprise Portal service, as described in [RFC 885](https://docs.google.com/document/d/1tiaW1IVKm_YSSYhH-z7Q8sv4HSO_YJ_Uu6eYDjX7uU4/edit#heading=h.tdaxc5h34u7q), with a test setup to verify that we are able to connect to the Sourcegraph.com database and query from it. This will be used to implement the read-only RPCs proposed in #62263 ## Test plan - [x] Publish image by hand: ```sh bazel run //cmd/enterprise-portal:candidate_push --stamp -- --tag insiders --repository us.gcr.io/sourcegraph-dev/enterprise-portal ``` - [x] Deploy in an MSP environment with appropriate permissions configured on the dotcom database, verify connection works: https://github.com/sourcegraph/managed-services/pull/1368 https://github.com/sourcegraph/managed-services/pull/1377
This commit is contained in:
parent
022b4ad95f
commit
e37a78bbd3
62
cmd/enterprise-portal/BUILD.bazel
Normal file
62
cmd/enterprise-portal/BUILD.bazel
Normal file
@ -0,0 +1,62 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
load("//dev:oci_defs.bzl", "image_repository", "oci_image", "oci_push", "oci_tarball")
|
||||
load("@rules_pkg//:pkg.bzl", "pkg_tar")
|
||||
load("@container_structure_test//:defs.bzl", "container_structure_test")
|
||||
|
||||
go_library(
|
||||
name = "enterprise-portal_lib",
|
||||
srcs = ["main.go"],
|
||||
importpath = "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//cmd/enterprise-portal/service",
|
||||
"//lib/managedservicesplatform/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "enterprise-portal",
|
||||
embed = [":enterprise-portal_lib"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "tar_enterprise-portal",
|
||||
srcs = [":enterprise-portal"],
|
||||
)
|
||||
|
||||
oci_image(
|
||||
name = "image",
|
||||
base = "//wolfi-images/sourcegraph-base:base_image",
|
||||
entrypoint = [
|
||||
"/sbin/tini",
|
||||
"--",
|
||||
"/enterprise-portal",
|
||||
],
|
||||
tars = [":tar_enterprise-portal"],
|
||||
user = "sourcegraph",
|
||||
)
|
||||
|
||||
oci_tarball(
|
||||
name = "image_tarball",
|
||||
image = ":image",
|
||||
repo_tags = ["enterprise-portal:candidate"],
|
||||
)
|
||||
|
||||
container_structure_test(
|
||||
name = "image_test",
|
||||
timeout = "short",
|
||||
configs = ["image_test.yaml"],
|
||||
driver = "docker",
|
||||
image = ":image",
|
||||
tags = [
|
||||
"exclusive",
|
||||
"requires-network",
|
||||
],
|
||||
)
|
||||
|
||||
oci_push(
|
||||
name = "candidate_push",
|
||||
image = ":image",
|
||||
repository = image_repository("enterprise-portal"),
|
||||
)
|
||||
3
cmd/enterprise-portal/CODENOTIFY
Normal file
3
cmd/enterprise-portal/CODENOTIFY
Normal file
@ -0,0 +1,3 @@
|
||||
# See https://github.com/sourcegraph/codenotify for documentation.
|
||||
|
||||
**/* @sourcegraph/core-services
|
||||
3
cmd/enterprise-portal/README.md
Normal file
3
cmd/enterprise-portal/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# enterprise-portal
|
||||
|
||||
**WIP** - refer to [RFC 885 Sourcegraph Enterprise Portal (go/enterprise-portal)](https://docs.google.com/document/d/1tiaW1IVKm_YSSYhH-z7Q8sv4HSO_YJ_Uu6eYDjX7uU4/edit#heading=h.tdaxc5h34u7q) for more details.
|
||||
15
cmd/enterprise-portal/image_test.yaml
Normal file
15
cmd/enterprise-portal/image_test.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
schemaVersion: "2.0.0"
|
||||
|
||||
commandTests:
|
||||
- name: "binary is runnable"
|
||||
command: "/enterprise-portal"
|
||||
envVars:
|
||||
- key: "SANITY_CHECK"
|
||||
value: "true"
|
||||
|
||||
- name: "not running as root"
|
||||
command: "/usr/bin/id"
|
||||
args:
|
||||
- -u
|
||||
excludedOutput: ["^0"]
|
||||
exitCode: 0
|
||||
12
cmd/enterprise-portal/internal/dotcomdb/BUILD.bazel
Normal file
12
cmd/enterprise-portal/internal/dotcomdb/BUILD.bazel
Normal file
@ -0,0 +1,12 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "dotcomdb",
|
||||
srcs = ["dotcomdb.go"],
|
||||
importpath = "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/dotcomdb",
|
||||
visibility = ["//cmd/enterprise-portal:__subpackages__"],
|
||||
deps = [
|
||||
"//lib/errors",
|
||||
"@com_github_jackc_pgx_v5//:pgx",
|
||||
],
|
||||
)
|
||||
32
cmd/enterprise-portal/internal/dotcomdb/dotcomdb.go
Normal file
32
cmd/enterprise-portal/internal/dotcomdb/dotcomdb.go
Normal file
@ -0,0 +1,32 @@
|
||||
package dotcomdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
conn *pgx.Conn
|
||||
}
|
||||
|
||||
// NewDatabase wraps a direct connection to the Sourcegraph.com database. It
|
||||
// ONLY executes read queries, so the connection can (and should) be
|
||||
// authenticated by a read-only user.
|
||||
func NewDatabase(conn *pgx.Conn) *Database {
|
||||
return &Database{conn: conn}
|
||||
}
|
||||
|
||||
func (d *Database) Ping(ctx context.Context) error {
|
||||
if err := d.conn.Ping(ctx); err != nil {
|
||||
return errors.Wrap(err, "sqlDB.PingContext")
|
||||
}
|
||||
if _, err := d.conn.Exec(ctx, "SELECT current_user;"); err != nil {
|
||||
return errors.Wrap(err, "sqlDB.Exec SELECT current_user")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Database) Close(ctx context.Context) error { return d.conn.Close(ctx) }
|
||||
10
cmd/enterprise-portal/main.go
Normal file
10
cmd/enterprise-portal/main.go
Normal file
@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/service"
|
||||
"github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.Start(&service.Service{})
|
||||
}
|
||||
25
cmd/enterprise-portal/service/BUILD.bazel
Normal file
25
cmd/enterprise-portal/service/BUILD.bazel
Normal file
@ -0,0 +1,25 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "service",
|
||||
srcs = [
|
||||
"config.go",
|
||||
"dotcomdb.go",
|
||||
"service.go",
|
||||
"state.go",
|
||||
],
|
||||
importpath = "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/service",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/enterprise-portal/internal/dotcomdb",
|
||||
"//internal/httpserver",
|
||||
"//internal/trace/policy",
|
||||
"//internal/version",
|
||||
"//lib/background",
|
||||
"//lib/errors",
|
||||
"//lib/managedservicesplatform/cloudsql",
|
||||
"//lib/managedservicesplatform/runtime",
|
||||
"@com_github_jackc_pgx_v5//:pgx",
|
||||
"@com_github_sourcegraph_log//:log",
|
||||
],
|
||||
)
|
||||
26
cmd/enterprise-portal/service/config.go
Normal file
26
cmd/enterprise-portal/service/config.go
Normal file
@ -0,0 +1,26 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/cloudsql"
|
||||
"github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/runtime"
|
||||
)
|
||||
|
||||
// Config is the configuration for the Enterprise Portal.
|
||||
type Config struct {
|
||||
DotComDB struct {
|
||||
cloudsql.ConnConfig
|
||||
|
||||
PGDSNOverride *string
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) Load(env *runtime.Env) {
|
||||
c.DotComDB.ConnConfig = cloudsql.ConnConfig{
|
||||
ConnectionName: env.GetOptional("DOTCOM_CLOUDSQL_CONNECTION_NAME",
|
||||
"Sourcegraph.com Cloud SQL connection name"),
|
||||
User: env.GetOptional("DOTCOM_CLOUDSQL_USER", "Sourcegraph.com Cloud SQL user"),
|
||||
Database: env.Get("DOTCOM_CLOUDSQL_DATABASE", "sourcegraph", "Sourcegraph.com database"),
|
||||
}
|
||||
c.DotComDB.PGDSNOverride = env.GetOptional("DOTCOM_PGDSN_OVERRIDE",
|
||||
"For local dev: custom PostgreSQL DSN, overrides DOTCOM_CLOUDSQL_* options")
|
||||
}
|
||||
32
cmd/enterprise-portal/service/dotcomdb.go
Normal file
32
cmd/enterprise-portal/service/dotcomdb.go
Normal file
@ -0,0 +1,32 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/dotcomdb"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/cloudsql"
|
||||
)
|
||||
|
||||
func newDotComDBConn(ctx context.Context, config Config) (*dotcomdb.Database, error) {
|
||||
if config.DotComDB.PGDSNOverride != nil {
|
||||
config, err := pgx.ParseConfig(*config.DotComDB.PGDSNOverride)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendered PGDSN is invalid")
|
||||
}
|
||||
conn, err := pgx.ConnectConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dotcomdb.NewDatabase(conn), nil
|
||||
}
|
||||
|
||||
// Use IAM auth to connect to the Cloud SQL database.
|
||||
conn, err := cloudsql.Connect(ctx, config.DotComDB.ConnConfig)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "contract.GetPostgreSQLDB")
|
||||
}
|
||||
return dotcomdb.NewDatabase(conn), nil
|
||||
}
|
||||
55
cmd/enterprise-portal/service/service.go
Normal file
55
cmd/enterprise-portal/service/service.go
Normal file
@ -0,0 +1,55 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/sourcegraph/log"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/httpserver"
|
||||
"github.com/sourcegraph/sourcegraph/internal/trace/policy"
|
||||
"github.com/sourcegraph/sourcegraph/internal/version"
|
||||
"github.com/sourcegraph/sourcegraph/lib/background"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/runtime"
|
||||
)
|
||||
|
||||
// Service is the implementation of the Enterprise Portal service.
|
||||
type Service struct{}
|
||||
|
||||
var _ runtime.Service[Config] = (*Service)(nil)
|
||||
|
||||
func (Service) Name() string { return "enterprise-portal" }
|
||||
func (Service) Version() string { return version.Version() }
|
||||
|
||||
func (Service) Initialize(ctx context.Context, logger log.Logger, contract runtime.Contract, config Config) (background.Routine, error) {
|
||||
// We use Sourcegraph tracing code, so explicitly configure a trace policy
|
||||
policy.SetTracePolicy(policy.TraceAll)
|
||||
|
||||
dotcomDB, err := newDotComDBConn(ctx, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newDotComDBConn")
|
||||
}
|
||||
defer dotcomDB.Close(context.Background())
|
||||
|
||||
// Simple test for now, move elsewhere later
|
||||
if err := dotcomDB.Ping(context.Background()); err != nil {
|
||||
return nil, errors.Wrap(err, "dotcomDB.Ping")
|
||||
}
|
||||
|
||||
httpServer := http.NewServeMux()
|
||||
contract.Diagnostics.RegisterDiagnosticsHandlers(httpServer, serviceState{})
|
||||
|
||||
listenAddr := fmt.Sprintf(":%d", contract.Port)
|
||||
server := httpserver.NewFromAddr(
|
||||
listenAddr,
|
||||
&http.Server{
|
||||
ReadTimeout: 2 * time.Minute,
|
||||
WriteTimeout: 2 * time.Minute,
|
||||
Handler: httpServer,
|
||||
},
|
||||
)
|
||||
return server, nil
|
||||
}
|
||||
10
cmd/enterprise-portal/service/state.go
Normal file
10
cmd/enterprise-portal/service/state.go
Normal file
@ -0,0 +1,10 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type serviceState struct{}
|
||||
|
||||
func (s serviceState) Healthy(_ context.Context, _ url.Values) error { return nil }
|
||||
2
go.mod
2
go.mod
@ -271,6 +271,7 @@ require (
|
||||
github.com/hashicorp/terraform-cdk-go/cdktf v0.17.3
|
||||
github.com/invopop/jsonschema v0.12.0
|
||||
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
|
||||
github.com/jackc/pgx/v5 v5.5.4
|
||||
github.com/jomei/notionapi v1.13.0
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
@ -379,7 +380,6 @@ require (
|
||||
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.4 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/knadh/koanf/v2 v2.0.1 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
|
||||
Loading…
Reference in New Issue
Block a user