mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 19:21:50 +00:00
Merge 17d5aeb1b7 into cff1669bc1
This commit is contained in:
commit
652ec406d6
@ -256,6 +256,7 @@ go_library(
|
||||
"//internal/actor",
|
||||
"//internal/adminanalytics",
|
||||
"//internal/api",
|
||||
"//internal/audit",
|
||||
"//internal/auth",
|
||||
"//internal/authz",
|
||||
"//internal/authz/permssync",
|
||||
@ -283,6 +284,7 @@ go_library(
|
||||
"//internal/embeddings/background/repo",
|
||||
"//internal/encryption",
|
||||
"//internal/encryption/keyring",
|
||||
"//internal/endpoint",
|
||||
"//internal/env",
|
||||
"//internal/errcode",
|
||||
"//internal/executor",
|
||||
@ -383,6 +385,8 @@ go_library(
|
||||
"@com_github_sourcegraph_zoekt//query",
|
||||
"@com_github_stretchr_testify//require",
|
||||
"@com_github_throttled_throttled_v2//:throttled",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
|
||||
"@io_k8s_apimachinery//pkg/types",
|
||||
"@io_opentelemetry_go_otel//:otel",
|
||||
"@io_opentelemetry_go_otel//attribute",
|
||||
"@org_golang_x_text//unicode/norm",
|
||||
|
||||
@ -175,7 +175,7 @@ func (r *siteResolver) SettingsURL() *string { return strptr("/site-admin/global
|
||||
|
||||
func (r *siteResolver) CanReloadSite(ctx context.Context) bool {
|
||||
err := auth.CheckCurrentUserIsSiteAdmin(ctx, r.db)
|
||||
return canReloadSite && err == nil
|
||||
return isGoremanSite && err == nil
|
||||
}
|
||||
|
||||
func (r *siteResolver) BuildVersion() string { return version.Version() }
|
||||
|
||||
@ -2,29 +2,70 @@ package graphqlbackend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/inconshreveable/log15" //nolint:logging // TODO move all logging to sourcegraph/log
|
||||
"github.com/sourcegraph/log"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/cmd/frontend/internal/processrestart"
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/audit"
|
||||
"github.com/sourcegraph/sourcegraph/internal/auth"
|
||||
"github.com/sourcegraph/sourcegraph/internal/cloud"
|
||||
"github.com/sourcegraph/sourcegraph/internal/endpoint"
|
||||
"github.com/sourcegraph/sourcegraph/internal/env"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
// canReloadSite is whether the current site can be reloaded via the API. Currently
|
||||
// only goreman-managed sites can be reloaded. Callers must also check if the actor
|
||||
// is an admin before actually reloading the site.
|
||||
var canReloadSite = processrestart.CanRestart()
|
||||
var isGoremanSite = processrestart.CanRestart()
|
||||
|
||||
// SRC_ENABLE_FRONTEND_SITE_RELOAD is env
|
||||
var enableFrontendSiteReload = env.MustGetBool("SRC_ENABLE_FRONTEND_SITE_RELOAD", true, "Enables the /reload-site endpoint for reloading the site")
|
||||
|
||||
func (r *schemaResolver) ReloadSite(ctx context.Context) (*EmptyResponse, error) {
|
||||
// 🚨 SECURITY: Reloading the site is an interruptive action, so only admins
|
||||
// 🚨 SECURITY: Reloading the site is an disruptive action, so only admins
|
||||
// may do it.
|
||||
if err := auth.CheckCurrentUserIsSiteAdmin(ctx, r.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !canReloadSite {
|
||||
if cloud.SiteConfig().SourcegraphOperatorAuthProviderEnabled() && enableFrontendSiteReload {
|
||||
// use k8s client to restart the frontend deployment rollout
|
||||
client, err := endpoint.LoadClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ns := endpoint.Namespace(r.logger)
|
||||
data := fmt.Sprintf(`{"spec": {"template": {"metadata": {"annotations": {"kubectl.kubernetes.io/restartedAt": "%s", "kubernetes.io/change-cause: "frontend restart requested"}}}}}`, time.Now().Format("20060102150405"))
|
||||
deploymentClient := client.AppsV1().Deployments(ns)
|
||||
|
||||
currentUser, err := CurrentUser(ctx, r.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
audit.Log(ctx, r.logger, audit.Record{
|
||||
Entity: "GraphQL",
|
||||
Action: "frontend-reload",
|
||||
Fields: []log.Field{
|
||||
log.String("currentUser", currentUser.user.Username),
|
||||
},
|
||||
})
|
||||
r.logger.Info("Restarting k8s deployment")
|
||||
_, err = deploymentClient.Patch(ctx, "sourcegraph-frontend",
|
||||
k8stypes.StrategicMergePatchType, []byte(data), metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EmptyResponse{}, nil
|
||||
}
|
||||
|
||||
if !isGoremanSite {
|
||||
return nil, errors.New("reloading site is not supported")
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ type endpoints struct {
|
||||
// New creates a new Map for the URL specifier.
|
||||
//
|
||||
// If the scheme is prefixed with "k8s+", one URL is expected and the format is
|
||||
// expected to match e.g. k8s+http://service.namespace:port/path. namespace,
|
||||
// expected to match e.g. k8s+http://service.namespace:port/path. Namespace,
|
||||
// port and path are optional. URLs of this form will consistently hash among
|
||||
// the endpoints for the Kubernetes service. The values returned by Get will
|
||||
// look like http://endpoint:port/path.
|
||||
|
||||
@ -27,7 +27,7 @@ func K8S(logger log.Logger, urlspec string) *Map {
|
||||
logger = logger.Scoped("k8s")
|
||||
return &Map{
|
||||
urlspec: urlspec,
|
||||
discofunk: k8sDiscovery(logger, urlspec, namespace(logger), loadClient),
|
||||
discofunk: k8sDiscovery(logger, urlspec, Namespace(logger), LoadClient),
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,10 +189,10 @@ func parseURL(rawurl string) (*k8sURL, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// namespace returns the namespace the pod is currently running in
|
||||
// this is done because the k8s client we previously used set the namespace
|
||||
// Namespace returns the Namespace the pod is currently running in
|
||||
// this is done because the k8s client we previously used set the Namespace
|
||||
// when the client was created, the official k8s client does not
|
||||
func namespace(logger log.Logger) string {
|
||||
func Namespace(logger log.Logger) string {
|
||||
logger = logger.Scoped("namespace")
|
||||
const filename = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
|
||||
data, err := os.ReadFile(filename)
|
||||
@ -209,7 +209,7 @@ func namespace(logger log.Logger) string {
|
||||
return ns
|
||||
}
|
||||
|
||||
func loadClient() (client *kubernetes.Clientset, err error) {
|
||||
func LoadClient() (client *kubernetes.Clientset, err error) {
|
||||
// Uncomment below to test against a real cluster. This is only important
|
||||
// when you are changing how we interact with the k8s API and you want to
|
||||
// test against the real thing.
|
||||
@ -226,7 +226,7 @@ func loadClient() (client *kubernetes.Clientset, err error) {
|
||||
}
|
||||
clientConfig := clientcmd.NewDefaultClientConfig(*c, nil)
|
||||
config, err = clientConfig.ClientConfig()
|
||||
namespace = "prod"
|
||||
Namespace = "prod"
|
||||
*/
|
||||
|
||||
config, err := rest.InClusterConfig()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user