Skip to content

CBG-4712 /_sgcollect_info endpoint to work with non default port #7601

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 24, 2025
Merged
26 changes: 26 additions & 0 deletions base/main_test_bucket_pool_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"strconv"
"testing"
"time"

"github.com/stretchr/testify/require"
)

// Bucket names start with a fixed prefix and end with a sequential bucket number and a creation timestamp for uniqueness
Expand Down Expand Up @@ -213,3 +215,27 @@ func TestClusterPassword() string {
}
return password
}

// TestRunSGCollectIntegrationTests runs the tests only if a specific environment variable is set. These should always run under jenkins/github actions.
func TestRunSGCollectIntegrationTests(t *testing.T) {
env := "SG_TEST_SGCOLLECT_INTEGRATION"
val, ok := os.LookupEnv(env)
if !ok {
ciEnvVars := []string{
"CI", // convention by github actions
"JENKINS_URL", // from jenkins
}
for _, ciEnv := range ciEnvVars {
if os.Getenv(ciEnv) != "" {
return
}
}
t.Skip("Skipping sgcollect integration tests - set " + env + "=true to run")
}

runTests, err := strconv.ParseBool(val)
require.NoError(t, err, "Couldn't parse %s=%s as bool", env, val)
if !runTests {
t.Skip("Skipping sgcollect integration tests - set " + env + "=true to run")
}
}
23 changes: 18 additions & 5 deletions rest/admin_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,7 @@ func (h *handler) handleSetLogging() error {

func (h *handler) handleSGCollectStatus() error {
status := "stopped"
if sgcollectInstance.IsRunning() {
if h.server.SGCollect.IsRunning() {
status = "running"
}

Expand All @@ -1647,7 +1647,7 @@ func (h *handler) handleSGCollectStatus() error {
}

func (h *handler) handleSGCollectCancel() error {
err := sgcollectInstance.Stop()
err := h.server.SGCollect.Stop()
if err != nil {
return base.HTTPErrorf(http.StatusBadRequest, "Error stopping sgcollect_info: %v", err)
}
Expand All @@ -1664,7 +1664,7 @@ func (h *handler) handleSGCollect() error {
return err
}

var params sgCollectOptions
var params SGCollectOptions
if err = base.JSONUnmarshal(body, &params); err != nil {
return base.HTTPErrorf(http.StatusBadRequest, "Unable to parse request body: %v", err)
}
Expand All @@ -1676,11 +1676,24 @@ func (h *handler) handleSGCollect() error {
// Populate username and password used by sgcollect_info script for talking to Sync Gateway.
params.syncGatewayUsername, params.syncGatewayPassword = h.getBasicAuth()

zipFilename := sgcollectFilename()
addr, err := h.server.getServerAddr(adminServer)
if err != nil {
return base.HTTPErrorf(http.StatusInternalServerError, "Error getting admin server address: %v", err)
}
if h.server.Config.API.HTTPS.TLSCertPath != "" {
addr = "https://" + addr
} else {
addr = "http://" + addr
}
params.adminURL = addr

zipFilename := SGCollectFilename()

logFilePath := h.server.Config.Logging.LogFilePath

if err := sgcollectInstance.Start(logFilePath, h.serialNumber, zipFilename, params); err != nil {
ctx := base.CorrelationIDLogCtx(context.WithoutCancel(h.ctx()), fmt.Sprintf("SGCollect-%03d", h.serialNumber))

if err := h.server.SGCollect.Start(ctx, logFilePath, zipFilename, params); err != nil {
return base.HTTPErrorf(http.StatusInternalServerError, "Error running sgcollect_info: %v", err)
}

Expand Down
8 changes: 4 additions & 4 deletions rest/audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func TestAuditLoggingFields(t *testing.T) {
auditableAction: func(t testing.TB) {
headers := map[string]string{
requestInfoHeaderName: `{"extra":"field"}`,
"Authorization": getBasicAuthHeader(requestUser, RestTesterDefaultUserPassword),
"Authorization": GetBasicAuthHeader(t, requestUser, RestTesterDefaultUserPassword),
}
RequireStatus(t, rt.SendRequestWithHeaders(http.MethodGet, "/db/", "", headers), http.StatusOK)
},
Expand Down Expand Up @@ -442,7 +442,7 @@ func TestAuditLoggingFields(t *testing.T) {
name: "metrics request authenticated",
auditableAction: func(t testing.TB) {
headers := map[string]string{
"Authorization": getBasicAuthHeader(base.TestClusterUsername(), base.TestClusterPassword()),
"Authorization": GetBasicAuthHeader(t, base.TestClusterUsername(), base.TestClusterPassword()),
}
RequireStatus(t, rt.SendMetricsRequestWithHeaders(http.MethodGet, "/_metrics", "", headers), http.StatusOK)
},
Expand Down Expand Up @@ -473,7 +473,7 @@ func TestAuditLoggingFields(t *testing.T) {
t.Skip("Skipping subtest that requires admin auth to be enabled")
}
headers := map[string]string{
"Authorization": getBasicAuthHeader("notauser", base.TestClusterPassword()),
"Authorization": GetBasicAuthHeader(t, "notauser", base.TestClusterPassword()),
}
RequireStatus(t, rt.SendMetricsRequestWithHeaders(http.MethodGet, "/_metrics", "", headers), http.StatusUnauthorized)
},
Expand Down Expand Up @@ -724,7 +724,7 @@ func TestEffectiveUserID(t *testing.T) {
)
reqHeaders := map[string]string{
"user_header": fmt.Sprintf(`{"%s": "%s", "%s":"%s"}`, headerDomain, cnfDomain, headerUser, cnfUser),
"Authorization": getBasicAuthHeader(realUser, RestTesterDefaultUserPassword),
"Authorization": GetBasicAuthHeader(t, realUser, RestTesterDefaultUserPassword),
}

rt := NewRestTester(t, &RestTesterConfig{
Expand Down
3 changes: 3 additions & 0 deletions rest/server_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ type ServerContext struct {
DatabaseInitManager *DatabaseInitManager // Manages database initialization (index creation and readiness) independent of database stop/start/reload, when using persistent config
ActiveReplicationsCounter
invalidDatabaseConfigTracking invalidDatabaseConfigs
// handle sgcollect processes for a given Server
SGCollect *sgCollect
}

type ActiveReplicationsCounter struct {
Expand Down Expand Up @@ -163,6 +165,7 @@ func NewServerContext(ctx context.Context, config *StartupConfig, persistentConf
BootstrapContext: &bootstrapContext{sgVersion: *base.ProductVersion},
hasStarted: make(chan struct{}),
_httpServers: map[serverType]*serverInfo{},
SGCollect: newSGCollect(ctx),
}
sc.invalidDatabaseConfigTracking = invalidDatabaseConfigs{
dbNames: map[string]*invalidConfigInfo{},
Expand Down
Loading
Loading