Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
cd workloadagentplatform
# this is the hash of the workloadagentplatform submodule
# get the hash by running: go list -m -json github.com/GoogleCloudPlatform/workloadagentplatform@main
git checkout d3f35daa40265bbdebb0539f86394de3d57b5b60
git checkout 14e5a69745b76ddb752fe6f0a3e556a2bf9b070a
cd ..
find workloadagentplatform/sharedprotos -type f -exec sed -i 's|"sharedprotos|"workloadagentplatform/sharedprotos|g' {} +
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/go-build-protos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
cd workloadagentplatform
# this is the hash of the workloadagentplatform submodule
# get the hash by running: go list -m -json github.com/GoogleCloudPlatform/workloadagentplatform@main
git checkout d3f35daa40265bbdebb0539f86394de3d57b5b60
git checkout 14e5a69745b76ddb752fe6f0a3e556a2bf9b070a
cd ..
find workloadagentplatform/sharedprotos -type f -exec sed -i 's|"sharedprotos|"workloadagentplatform/sharedprotos|g' {} +
env:
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ if [ "${COMPILE_PROTOS}" == "TRUE" ] && [ ! -d "workloadagentplatform" ]; then
cd workloadagentplatform
# this is the hash of the workloadagentplatform submodule
# get the hash by running: go list -m -json github.com/GoogleCloudPlatform/workloadagentplatform@main
git checkout d3f35daa40265bbdebb0539f86394de3d57b5b60
git checkout 14e5a69745b76ddb752fe6f0a3e556a2bf9b070a
cd ..
# replace the proto imports in the platform that reference the platform
find workloadagentplatform/sharedprotos -type f -exec sed -i 's|"sharedprotos|"workloadagentplatform/sharedprotos|g' {} +
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ require (
github.com/DATA-DOG/go-sqlmock v1.5.0
// Get the version by running:
// go list -m -json github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries@main
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260129072723-d3f35daa4026
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260204142957-14e5a69745b7
// Get the version by running:
// go list -m -json github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos@main
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260129072723-d3f35daa4026
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260204142957-14e5a69745b7
github.com/StackExchange/wmi v1.2.1
github.com/cenkalti/backoff/v4 v4.3.0
github.com/gammazero/workerpool v1.1.3
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260129072723-d3f35daa4026 h1:A1mejaVO5CGRCNbE3/VBuiMV2fFVfShDTVOQv3uqIxo=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260129072723-d3f35daa4026/go.mod h1:WrwTr9HFkp+nbHba/tv36eCLkjKAeCx7mqiG/wL3PNU=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260129072723-d3f35daa4026 h1:ltjiVZbCTOmtu1z/K0IdEEB8MWnD78EB6sQ2U0sLhI8=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260129072723-d3f35daa4026/go.mod h1:8Ea8vdBuPsWhhwzL9sNK7BFQE9qbkPLZUHxcucWHXaM=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260204142957-14e5a69745b7 h1:HCpDNgKlkacUMg2g7dyZUXBvYGg6hA3oU1T/EozIIJA=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries v0.0.0-20260204142957-14e5a69745b7/go.mod h1:WrwTr9HFkp+nbHba/tv36eCLkjKAeCx7mqiG/wL3PNU=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260204142957-14e5a69745b7 h1:0dqOik6XXF6bCxIjTGrmCJ69tvOmNFQThFReP6n2b/U=
github.com/GoogleCloudPlatform/workloadagentplatform/sharedprotos v0.0.0-20260204142957-14e5a69745b7/go.mod h1:8Ea8vdBuPsWhhwzL9sNK7BFQE9qbkPLZUHxcucWHXaM=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
Expand Down
125 changes: 113 additions & 12 deletions internal/onetime/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,30 @@ import (
"context"
_ "embed"
"fmt"
"io"
"os"
"runtime"
"slices"
"strings"
"time"

"cloud.google.com/go/artifactregistry/apiv1"
"github.com/spf13/cobra"
"google.golang.org/api/googleapi"
"google.golang.org/api/serviceusage/v1"
"google.golang.org/protobuf/encoding/protojson"
"github.com/GoogleCloudPlatform/workloadagent/internal/daemon/configuration"
"github.com/GoogleCloudPlatform/workloadagent/internal/mongodbmetrics"
"github.com/GoogleCloudPlatform/workloadagent/internal/mysqlmetrics"
"github.com/GoogleCloudPlatform/workloadagent/internal/oraclemetrics"
"github.com/GoogleCloudPlatform/workloadagent/internal/postgresmetrics"
"github.com/GoogleCloudPlatform/workloadagent/internal/redismetrics"
"github.com/GoogleCloudPlatform/workloadagent/internal/sqlservermetrics/sqlcollector"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/commandlineexecutor"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/gce"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/iam"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/log"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/osinfo"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/permissions"
"github.com/GoogleCloudPlatform/workloadagentplatform/sharedlibraries/statushelper"

Expand All @@ -54,6 +64,10 @@ var serviceUsageNewService = func(ctx context.Context) (*serviceusage.Service, e
return serviceusage.NewService(ctx)
}

var newGCEClient = func(ctx context.Context) (gceInterface, error) {
return gce.NewGCEClient(ctx)
}

// NewCommand creates a new status command.
func NewCommand(cloudProps *cpb.CloudProperties) *cobra.Command {
var config string
Expand Down Expand Up @@ -150,20 +164,19 @@ func agentStatus(ctx context.Context, arClient statushelper.ARClientInterface, i
}
}
agentStatus.ConfigurationFilePath = path
func() {
configProto := &cpb.Configuration{}
validate := func() error {
content, err := readFile(path)
if err != nil {
agentStatus.ConfigurationValid = spb.State_FAILURE_STATE
agentStatus.ConfigurationErrorMessage = err.Error()
return
}
configProto := &cpb.Configuration{}
agentStatus.ConfigurationValid = spb.State_SUCCESS_STATE
if err := protojson.Unmarshal(content, configProto); err != nil {
agentStatus.ConfigurationValid = spb.State_FAILURE_STATE
agentStatus.ConfigurationErrorMessage = err.Error()
return err
}
}()
return protojson.Unmarshal(content, configProto)
}
agentStatus.ConfigurationValid = spb.State_SUCCESS_STATE
if err := validate(); err != nil {
agentStatus.ConfigurationValid = spb.State_FAILURE_STATE
agentStatus.ConfigurationErrorMessage = err.Error()
}

// Check IAM permissions for configured services
iamServices := map[string]string{
Expand All @@ -177,6 +190,21 @@ func agentStatus(ctx context.Context, arClient statushelper.ARClientInterface, i
}
agentStatus.Services = append(agentStatus.Services, checkAPIEnablement(ctx, cloudProps, apis)...)

// Check database connectivity if the configuration is valid
if agentStatus.GetConfigurationValid() == spb.State_SUCCESS_STATE {
gceService, err := newGCEClient(ctx)
if err != nil {
log.CtxLogger(ctx).Errorw("Could not create GCE client, skipping database connectivity checks.", "error", err)
agentStatus.Services = append(agentStatus.Services, &spb.ServiceStatus{
Name: "GCE Connectivity",
State: spb.State_FAILURE_STATE,
ErrorMessage: fmt.Sprintf("Could not create GCE client: %v", err),
})
} else {
checkDatabaseConnectivity(ctx, configProto, gceService, agentStatus, cloudProps)
}
}

agentStatus.KernelVersion, err = statushelper.KernelVersion(ctx, runtime.GOOS, exec)
if err != nil && runtime.GOOS == "linux" {
log.CtxLogger(ctx).Errorw("Could not fetch kernel version", "error", err)
Expand Down Expand Up @@ -227,7 +255,7 @@ func checkIAMPermissions(ctx context.Context, iamClient permissions.IAMService,
status.ErrorMessage = err.Error()
status.FullyFunctional = spb.State_FAILURE_STATE
} else {
log.CtxLogger(ctx).Infow("IAM Permissions", "service", serviceName, "permissions", grantedPermissions)
log.CtxLogger(ctx).Debugw("IAM Permissions", "service", serviceName, "permissions", grantedPermissions)
status.State = spb.State_SUCCESS_STATE
status.FullyFunctional = spb.State_SUCCESS_STATE
for permission, granted := range grantedPermissions {
Expand Down Expand Up @@ -321,6 +349,79 @@ func checkAPIEnablement(ctx context.Context, cloudProps *cpb.CloudProperties, ap
return statuses
}

type gceInterface interface {
GetSecret(ctx context.Context, projectID, secretName string) (string, error)
}

func checkAndSetStatus(name string, checkFn func() error) *spb.ServiceStatus {
s := &spb.ServiceStatus{Name: name}
if err := checkFn(); err != nil {
s.State = spb.State_ERROR_STATE
s.ErrorMessage = err.Error()
} else {
s.State = spb.State_SUCCESS_STATE
s.FullyFunctional = spb.State_SUCCESS_STATE
}
return s
}

func checkDatabaseConnectivity(ctx context.Context, cfg *cpb.Configuration, gceService gceInterface, status *spb.AgentStatus, cloudProps *cpb.CloudProperties) {
// Database Connectivity Checks for MySQL
if cfg.GetMysqlConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("mysql", func() error {
metrics := mysqlmetrics.New(ctx, cfg, nil, nil)
return metrics.InitDB(ctx, gceService)
}))
}

// Database Connectivity Checks for PostgreSQL
if cfg.GetPostgresConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("postgres", func() error {
metrics := postgresmetrics.New(ctx, cfg, nil, nil)
return metrics.InitDB(ctx, gceService)
}))
}

// Database Connectivity Checks for MongoDB
if cfg.GetMongoDbConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("mongodb", func() error {
metrics := mongodbmetrics.New(ctx, cfg, nil, nil, mongodbmetrics.DefaultRunCommand)
return metrics.InitDB(ctx, gceService, 10*time.Second)
}))
}

// Database Connectivity Checks for Redis
if cfg.GetRedisConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("redis", func() error {
osOpenFile := func(f string) (io.ReadCloser, error) { return os.Open(f) }
osData, err := osinfo.ReadData(ctx, osOpenFile, runtime.GOOS, osinfo.OSReleaseFilePath)
if err != nil {
return fmt.Errorf("could not read OS info: %w", err)
}
metrics := redismetrics.New(ctx, cfg, nil, osData)
return metrics.InitDB(ctx, gceService)
}))
}

// Database Connectivity Checks for Oracle
if cfg.GetOracleConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("oracle", func() error {
metrics := oraclemetrics.MetricCollector{
Config: cfg,
GCEService: gceService,
}
return metrics.PingTest(ctx)
}))
}

// Database Connectivity Checks for SQL Server
if cfg.GetSqlserverConfiguration().GetEnabled() {
status.Services = append(status.Services, checkAndSetStatus("sqlserver", func() error {
return sqlcollector.PingSQLServer(ctx, cfg.GetSqlserverConfiguration(), gceService, cloudProps)
}))
}
}

// getRepositoryLocation returns the repository location based on the cloud properties.
func getRepositoryLocation(cp *cpb.CloudProperties) string {
if cp.GetZone() == "" {
Expand Down
Loading
Loading