Skip to content

Commit c3d390f

Browse files
authored
GODRIVER-2906 Add container Env to Handshake. (#1382)
1 parent f192906 commit c3d390f

File tree

2 files changed

+122
-23
lines changed

2 files changed

+122
-23
lines changed

x/mongo/driver/operation/hello.go

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,23 @@ const (
153153
envNameVercel = "vercel"
154154
)
155155

156+
const dockerEnvPath = "/.dockerenv"
157+
const envVarK8s = "KUBERNETES_SERVICE_HOST"
158+
159+
const (
160+
// Runtime names
161+
runtimeNameDocker = "docker"
162+
163+
// Orchestrator names
164+
orchestratorNameK8s = "kubernetes"
165+
)
166+
156167
// getFaasEnvName parses the FaaS environment variable name and returns the
157168
// corresponding name used by the client. If none of the variables or variables
158-
// for multiple names are populated the client.env value MUST be entirely
159-
// omitted. When variables for multiple "client.env.name" values are present,
160-
// "vercel" takes precedence over "aws.lambda"; any other combination MUST cause
161-
// "client.env" to be entirely omitted.
169+
// for multiple names are populated the FaaS values MUST be entirely omitted.
170+
// When variables for multiple "client.env.name" values are present, "vercel"
171+
// takes precedence over "aws.lambda"; any other combination MUST cause FaaS
172+
// values to be entirely omitted.
162173
func getFaasEnvName() string {
163174
envVars := []string{
164175
envVarAWSExecutionEnv,
@@ -218,6 +229,31 @@ func getFaasEnvName() string {
218229
return ""
219230
}
220231

232+
type containerInfo struct {
233+
runtime string
234+
orchestrator string
235+
}
236+
237+
// getContainerEnvInfo returns runtime and orchestrator of a container.
238+
// If no fields is populated, the client.env.container value MUST be entirely
239+
// omitted.
240+
func getContainerEnvInfo() *containerInfo {
241+
var runtime, orchestrator string
242+
if _, err := os.Stat(dockerEnvPath); !os.IsNotExist(err) {
243+
runtime = runtimeNameDocker
244+
}
245+
if v := os.Getenv(envVarK8s); v != "" {
246+
orchestrator = orchestratorNameK8s
247+
}
248+
if runtime != "" || orchestrator != "" {
249+
return &containerInfo{
250+
runtime: runtime,
251+
orchestrator: orchestrator,
252+
}
253+
}
254+
return nil
255+
}
256+
221257
// appendClientAppName appends the application metadata to the dst. It is the
222258
// responsibility of the caller to check that this appending does not cause dst
223259
// to exceed any size limitations.
@@ -256,14 +292,20 @@ func appendClientEnv(dst []byte, omitNonName, omitDoc bool) ([]byte, error) {
256292
}
257293

258294
name := getFaasEnvName()
259-
if name == "" {
295+
container := getContainerEnvInfo()
296+
// Omit the entire 'env' if both name and container are empty because other
297+
// fields depend on either of them.
298+
if name == "" && container == nil {
260299
return dst, nil
261300
}
262301

263302
var idx int32
264303

265304
idx, dst = bsoncore.AppendDocumentElementStart(dst, "env")
266-
dst = bsoncore.AppendStringElement(dst, "name", name)
305+
306+
if name != "" {
307+
dst = bsoncore.AppendStringElement(dst, "name", name)
308+
}
267309

268310
addMem := func(envVar string) []byte {
269311
mem := os.Getenv(envVar)
@@ -306,6 +348,7 @@ func appendClientEnv(dst []byte, omitNonName, omitDoc bool) ([]byte, error) {
306348
}
307349

308350
if !omitNonName {
351+
// No other FaaS fields will be populated if the name is empty.
309352
switch name {
310353
case envNameAWSLambda:
311354
dst = addMem(envVarAWSLambdaFunctionMemorySize)
@@ -319,6 +362,22 @@ func appendClientEnv(dst []byte, omitNonName, omitDoc bool) ([]byte, error) {
319362
}
320363
}
321364

365+
if container != nil {
366+
var idxCntnr int32
367+
idxCntnr, dst = bsoncore.AppendDocumentElementStart(dst, "container")
368+
if container.runtime != "" {
369+
dst = bsoncore.AppendStringElement(dst, "runtime", container.runtime)
370+
}
371+
if container.orchestrator != "" {
372+
dst = bsoncore.AppendStringElement(dst, "orchestrator", container.orchestrator)
373+
}
374+
var err error
375+
dst, err = bsoncore.AppendDocumentEnd(dst, idxCntnr)
376+
if err != nil {
377+
return dst, err
378+
}
379+
}
380+
322381
return bsoncore.AppendDocumentEnd(dst, idx)
323382
}
324383

@@ -358,21 +417,25 @@ func appendClientPlatform(dst []byte) []byte {
358417
// name: "<string>"
359418
// },
360419
// driver: {
361-
// name: "<string>",
362-
// version: "<string>"
420+
// name: "<string>",
421+
// version: "<string>"
363422
// },
364423
// platform: "<string>",
365424
// os: {
366-
// type: "<string>",
367-
// name: "<string>",
368-
// architecture: "<string>",
369-
// version: "<string>"
425+
// type: "<string>",
426+
// name: "<string>",
427+
// architecture: "<string>",
428+
// version: "<string>"
370429
// },
371430
// env: {
372-
// name: "<string>",
373-
// timeout_sec: 42,
374-
// memory_mb: 1024,
375-
// region: "<string>",
431+
// name: "<string>",
432+
// timeout_sec: 42,
433+
// memory_mb: 1024,
434+
// region: "<string>",
435+
// container: {
436+
// runtime: "<string>",
437+
// orchestrator: "<string>"
438+
// }
376439
// }
377440
// }
378441
func encodeClientMetadata(appname string, maxLen int) ([]byte, error) {

x/mongo/driver/operation/hello_test.go

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@ func TestAppendClientEnv(t *testing.T) {
272272
},
273273
want: []byte(`{"env":{"name":"azure.func"}}`),
274274
},
275+
{
276+
name: "k8s",
277+
env: map[string]string{
278+
envVarK8s: "0.0.0.0",
279+
},
280+
want: []byte(`{"env":{"container":{"orchestrator":"kubernetes"}}}`),
281+
},
282+
// client.env.container.runtime is untested.
275283
}
276284

277285
for _, test := range tests {
@@ -382,11 +390,17 @@ func TestEncodeClientMetadata(t *testing.T) {
382390
Architecture string `bson:"architecture,omitempty"`
383391
}
384392

393+
type container struct {
394+
Runtime string `bson:"runtime,omitempty"`
395+
Orchestrator string `bson:"orchestrator,omitempty"`
396+
}
397+
385398
type env struct {
386-
Name string `bson:"name,omitempty"`
387-
TimeoutSec int64 `bson:"timeout_sec,omitempty"`
388-
MemoryMB int32 `bson:"memory_mb,omitempty"`
389-
Region string `bson:"region,omitempty"`
399+
Name string `bson:"name,omitempty"`
400+
TimeoutSec int64 `bson:"timeout_sec,omitempty"`
401+
MemoryMB int32 `bson:"memory_mb,omitempty"`
402+
Region string `bson:"region,omitempty"`
403+
Container *container `bson:"container,omitempty"`
390404
}
391405

392406
type clientMetadata struct {
@@ -408,6 +422,7 @@ func TestEncodeClientMetadata(t *testing.T) {
408422
t.Setenv(envVarAWSLambdaRuntimeAPI, "lambda")
409423
t.Setenv(envVarAWSLambdaFunctionMemorySize, "123")
410424
t.Setenv(envVarAWSRegion, "us-east-2")
425+
t.Setenv(envVarK8s, "0.0.0.0")
411426

412427
t.Run("nothing is omitted", func(t *testing.T) {
413428
got, err := encodeClientMetadata("foo", maxClientMetadataSize)
@@ -418,7 +433,14 @@ func TestEncodeClientMetadata(t *testing.T) {
418433
Driver: &driver{Name: driverName, Version: version.Driver},
419434
OS: &dist{Type: runtime.GOOS, Architecture: runtime.GOARCH},
420435
Platform: runtime.Version(),
421-
Env: &env{Name: envNameAWSLambda, MemoryMB: 123, Region: "us-east-2"},
436+
Env: &env{
437+
Name: envNameAWSLambda,
438+
MemoryMB: 123,
439+
Region: "us-east-2",
440+
Container: &container{
441+
Orchestrator: "kubernetes",
442+
},
443+
},
422444
})
423445

424446
assertDocsEqual(t, got, want)
@@ -437,7 +459,12 @@ func TestEncodeClientMetadata(t *testing.T) {
437459
Driver: &driver{Name: driverName, Version: version.Driver},
438460
OS: &dist{Type: runtime.GOOS, Architecture: runtime.GOARCH},
439461
Platform: runtime.Version(),
440-
Env: &env{Name: envNameAWSLambda},
462+
Env: &env{
463+
Name: envNameAWSLambda,
464+
Container: &container{
465+
Orchestrator: "kubernetes",
466+
},
467+
},
441468
})
442469

443470
assertDocsEqual(t, got, want)
@@ -454,6 +481,10 @@ func TestEncodeClientMetadata(t *testing.T) {
454481

455482
// Calculate what the env.name costs.
456483
ndst := bsoncore.AppendStringElement(nil, "name", envNameAWSLambda)
484+
idx, ndst := bsoncore.AppendDocumentElementStart(ndst, "container")
485+
ndst = bsoncore.AppendStringElement(ndst, "orchestrator", "kubernetes")
486+
ndst, err = bsoncore.AppendDocumentEnd(ndst, idx)
487+
require.NoError(t, err)
457488

458489
// Environment sub name.
459490
envSubName := len(edst) - len(ndst)
@@ -466,7 +497,12 @@ func TestEncodeClientMetadata(t *testing.T) {
466497
Driver: &driver{Name: driverName, Version: version.Driver},
467498
OS: &dist{Type: runtime.GOOS},
468499
Platform: runtime.Version(),
469-
Env: &env{Name: envNameAWSLambda},
500+
Env: &env{
501+
Name: envNameAWSLambda,
502+
Container: &container{
503+
Orchestrator: "kubernetes",
504+
},
505+
},
470506
})
471507

472508
assertDocsEqual(t, got, want)

0 commit comments

Comments
 (0)