Skip to content

Commit

Permalink
stats/opentelemetry/csm: Get mesh_id local label from "CSM_MESH_ID" …
Browse files Browse the repository at this point in the history
…environment variable, rather than parsing from bootstrap file (grpc#7740)
  • Loading branch information
zasweq authored Oct 15, 2024
1 parent ad81c20 commit 54841ef
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 98 deletions.
22 changes: 12 additions & 10 deletions stats/opentelemetry/csm/observability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import (
"google.golang.org/grpc/encoding/gzip"
istats "google.golang.org/grpc/internal/stats"
"google.golang.org/grpc/internal/stubserver"
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/internal/testutils/xds/e2e"
testgrpc "google.golang.org/grpc/interop/grpc_testing"
testpb "google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/metadata"
Expand All @@ -46,12 +44,11 @@ import (
// Env Vars as well, and mocks the resource detector's returned attribute set to
// simulate the environment. It registers a cleanup function on the provided t
// to restore the environment to its original state.
func setupEnv(t *testing.T, resourceDetectorEmissions map[string]string, nodeID, csmCanonicalServiceName, csmWorkloadName string) {
bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, "xds_server_uri")
testutils.CreateBootstrapFileForTesting(t, bootstrapContents)

func setupEnv(t *testing.T, resourceDetectorEmissions map[string]string, meshID, csmCanonicalServiceName, csmWorkloadName string) {
oldCSMMeshID, csmMeshIDPresent := os.LookupEnv("CSM_MESH_ID")
oldCSMCanonicalServiceName, csmCanonicalServiceNamePresent := os.LookupEnv("CSM_CANONICAL_SERVICE_NAME")
oldCSMWorkloadName, csmWorkloadNamePresent := os.LookupEnv("CSM_WORKLOAD_NAME")
os.Setenv("CSM_MESH_ID", meshID)
os.Setenv("CSM_CANONICAL_SERVICE_NAME", csmCanonicalServiceName)
os.Setenv("CSM_WORKLOAD_NAME", csmWorkloadName)

Expand All @@ -67,6 +64,11 @@ func setupEnv(t *testing.T, resourceDetectorEmissions map[string]string, nodeID,
return &attrSet
}
t.Cleanup(func() {
if csmMeshIDPresent {
os.Setenv("CSM_MESH_ID", oldCSMMeshID)
} else {
os.Unsetenv("CSM_MESH_ID")
}
if csmCanonicalServiceNamePresent {
os.Setenv("CSM_CANONICAL_SERVICE_NAME", oldCSMCanonicalServiceName)
} else {
Expand Down Expand Up @@ -99,10 +101,10 @@ func (s) TestCSMPluginOptionUnary(t *testing.T) {
"k8s.namespace.name": "k8s_namespace_name_val",
"k8s.cluster.name": "k8s_cluster_name_val",
}
const nodeID = "projects/12345/networks/mesh:mesh_id/nodes/aaaa-aaaa-aaaa-aaaa"
const meshID = "mesh_id"
const csmCanonicalServiceName = "csm_canonical_service_name"
const csmWorkloadName = "csm_workload_name"
setupEnv(t, resourceDetectorEmissions, nodeID, csmCanonicalServiceName, csmWorkloadName)
setupEnv(t, resourceDetectorEmissions, meshID, csmCanonicalServiceName, csmWorkloadName)

attributesWant := map[string]string{
"csm.workload_canonical_service": csmCanonicalServiceName, // from env
Expand Down Expand Up @@ -266,10 +268,10 @@ func (s) TestCSMPluginOptionStreaming(t *testing.T) {
"k8s.namespace.name": "k8s_namespace_name_val",
"k8s.cluster.name": "k8s_cluster_name_val",
}
const nodeID = "projects/12345/networks/mesh:mesh_id/nodes/aaaa-aaaa-aaaa-aaaa"
const meshID = "mesh_id"
const csmCanonicalServiceName = "csm_canonical_service_name"
const csmWorkloadName = "csm_workload_name"
setupEnv(t, resourceDetectorEmissions, nodeID, csmCanonicalServiceName, csmWorkloadName)
setupEnv(t, resourceDetectorEmissions, meshID, csmCanonicalServiceName, csmWorkloadName)

attributesWant := map[string]string{
"csm.workload_canonical_service": csmCanonicalServiceName, // from env
Expand Down
37 changes: 1 addition & 36 deletions stats/opentelemetry/csm/pluginoption.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@ import (
"encoding/base64"
"net/url"
"os"
"strings"

"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal/xds/bootstrap"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/stats/opentelemetry/internal"

"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"

Expand Down Expand Up @@ -233,24 +230,6 @@ func constructMetadataFromEnv(ctx context.Context) (map[string]string, string) {
return initializeLocalAndMetadataLabels(labels)
}

// parseMeshIDString parses the mesh id from the node id according to the format
// "projects/[GCP Project number]/networks/mesh:[Mesh ID]/nodes/[UUID]". Returns
// "unknown" if there is a syntax error in the node ID.
func parseMeshIDFromNodeID(nodeID string) string {
meshSplit := strings.Split(nodeID, "/")
if len(meshSplit) != 6 {
return "unknown"
}
if meshSplit[0] != "projects" || meshSplit[2] != "networks" || meshSplit[4] != "nodes" {
return "unknown"
}
meshID, ok := strings.CutPrefix(meshSplit[3], "mesh:")
if !ok { // errors become "unknown"
return "unknown"
}
return meshID
}

// initializeLocalAndMetadataLabels csm local labels for a CSM Plugin Option to
// record. It also builds out a base 64 encoded protobuf.Struct containing the
// metadata exchange labels to be sent as part of metadata exchange from a CSM
Expand All @@ -261,9 +240,7 @@ func initializeLocalAndMetadataLabels(labels map[string]string) (map[string]stri
val := labels["canonical_service"]
localLabels := make(map[string]string)
localLabels["csm.workload_canonical_service"] = val
// Get the CSM Mesh ID from the bootstrap file.
nodeID := getNodeID()
localLabels["csm.mesh_id"] = parseMeshIDFromNodeID(nodeID)
localLabels["csm.mesh_id"] = getEnv("CSM_MESH_ID")

// Metadata exchange labels - can go ahead and encode into proto, and then
// base64.
Expand All @@ -288,18 +265,6 @@ func initializeLocalAndMetadataLabels(labels map[string]string) (map[string]stri
return localLabels, metadataExchangeLabelsEncoded
}

// getNodeID gets the Node ID from the bootstrap data.
func getNodeID() string {
cfg, err := bootstrap.GetConfiguration()
if err != nil {
return "" // will become "unknown"
}
if cfg.Node() == nil {
return ""
}
return cfg.Node().GetId()
}

// metadataExchangeKey is the key for HTTP metadata exchange.
const metadataExchangeKey = "x-envoy-peer-metadata"

Expand Down
57 changes: 5 additions & 52 deletions stats/opentelemetry/csm/pluginoption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ import (

"google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/internal/grpctest"
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/internal/testutils/xds/e2e"
"google.golang.org/grpc/metadata"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -304,51 +302,6 @@ func (s) TestDetermineTargetCSM(t *testing.T) {
}
}

func (s) TestBootstrap(t *testing.T) {
tests := []struct {
name string
nodeID string
meshIDWant string
}{
{
name: "malformed-node-id-unknown",
nodeID: "malformed",
meshIDWant: "unknown",
},
{
name: "node-id-parsed",
nodeID: "projects/12345/networks/mesh:mesh_id/nodes/aaaa-aaaa-aaaa-aaaa",
meshIDWant: "mesh_id",
},
{
name: "wrong-syntax-unknown",
nodeID: "wrong-syntax/12345/networks/mesh:mesh_id/nodes/aaaa-aaaa-aaaa-aaaa",
meshIDWant: "unknown",
},
{
name: "node-id-parsed",
nodeID: "projects/12345/networks/mesh:/nodes/aaaa-aaaa-aaaa-aaaa",
meshIDWant: "",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
bootstrapContents := e2e.DefaultBootstrapContents(t, test.nodeID, "xds_server_uri")
testutils.CreateBootstrapFileForTesting(t, bootstrapContents)
nodeIDGot := getNodeID() // this should return the node ID plumbed into bootstrap above
if nodeIDGot != test.nodeID {
t.Fatalf("getNodeID: got %v, want %v", nodeIDGot, test.nodeID)
}

meshIDGot := parseMeshIDFromNodeID(nodeIDGot)
if meshIDGot != test.meshIDWant {
t.Fatalf("parseMeshIDFromNodeID(%v): got %v, want %v", nodeIDGot, meshIDGot, test.meshIDWant)
}
})
}
}

// TestSetLabels tests the setting of labels, which snapshots the resource and
// environment. It mocks the resource and environment, and then calls into
// labels creation. It verifies to local labels created and metadata exchange
Expand All @@ -360,14 +313,14 @@ func (s) TestSetLabels(t *testing.T) {
resourceKeyValues map[string]string
csmCanonicalServiceNamePopulated bool
csmWorkloadNamePopulated bool
bootstrapGeneratorPopulated bool
meshIDPopulated bool
localLabelsWant map[string]string
metadataExchangeLabelsWant map[string]string
}{
{
name: "no-type",
csmCanonicalServiceNamePopulated: true,
bootstrapGeneratorPopulated: true,
meshIDPopulated: true,
resourceKeyValues: map[string]string{},
localLabelsWant: map[string]string{
"csm.workload_canonical_service": "canonical_service_name_val", // env var populated so should be set.
Expand Down Expand Up @@ -480,9 +433,9 @@ func (s) TestSetLabels(t *testing.T) {
os.Setenv("CSM_WORKLOAD_NAME", "workload_name_val")
defer os.Unsetenv("CSM_WORKLOAD_NAME")
}
if test.bootstrapGeneratorPopulated {
bootstrapContents := e2e.DefaultBootstrapContents(t, "projects/12345/networks/mesh:mesh_id/nodes/aaaa-aaaa-aaaa-aaaa", "xds_server_uri")
testutils.CreateBootstrapFileForTesting(t, bootstrapContents)
if test.meshIDPopulated {
os.Setenv("CSM_MESH_ID", "mesh_id")
defer os.Unsetenv("CSM_MESH_ID")
}
var attributes []attribute.KeyValue
for k, v := range test.resourceKeyValues {
Expand Down

0 comments on commit 54841ef

Please sign in to comment.