Skip to content

Commit

Permalink
xds: Add a package to hold environment variables. (#4002)
Browse files Browse the repository at this point in the history
  • Loading branch information
easwars authored Nov 4, 2020
1 parent 9a3c661 commit ea89aca
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 49 deletions.
24 changes: 7 additions & 17 deletions xds/internal/client/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"os"

v2corepb "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
Expand All @@ -35,14 +34,11 @@ import (
"google.golang.org/grpc/credentials/google"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/xds/internal/env"
"google.golang.org/grpc/xds/internal/version"
)

const (
// Environment variable which holds the name of the xDS bootstrap file.
bootstrapFileEnv = "GRPC_XDS_BOOTSTRAP"
// Environment variable which controls the use of xDS v3 API.
v3SupportEnv = "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT"
// The "server_features" field in the bootstrap file contains a list of
// features supported by the server. A value of "xds_v3" indicates that the
// server supports the v3 version of the xDS transport protocol.
Expand Down Expand Up @@ -142,11 +138,11 @@ type xdsServer struct {
func NewConfig() (*Config, error) {
config := &Config{}

fName, ok := os.LookupEnv(bootstrapFileEnv)
if !ok {
return nil, fmt.Errorf("xds: Environment variable %v not defined", bootstrapFileEnv)
fName := env.BootstrapFileName
if fName == "" {
return nil, fmt.Errorf("xds: Environment variable %q not defined", "GRPC_XDS_BOOTSTRAP")
}
logger.Infof("Got bootstrap file location from %v environment variable: %v", bootstrapFileEnv, fName)
logger.Infof("Got bootstrap file location %q", fName)

data, err := bootstrapFileReadFunc(fName)
if err != nil {
Expand Down Expand Up @@ -259,14 +255,8 @@ func NewConfig() (*Config, error) {
// 2. Environment variable "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT" is set to
// true.
// The default value of the enum type "version.TransportAPI" is v2.
//
// TODO: there are multiple env variables, GRPC_XDS_BOOTSTRAP and
// GRPC_XDS_EXPERIMENTAL_V3_SUPPORT. Move all env variables into a separate
// package.
if v3Env := os.Getenv(v3SupportEnv); v3Env == "true" {
if serverSupportsV3 {
config.TransportAPI = version.TransportV3
}
if env.V3Support && serverSupportsV3 {
config.TransportAPI = version.TransportV3
}

if err := config.updateNodeProto(); err != nil {
Expand Down
67 changes: 35 additions & 32 deletions xds/internal/client/bootstrap/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"google.golang.org/grpc/credentials/google"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/xds/internal/env"
"google.golang.org/grpc/xds/internal/version"
)

Expand Down Expand Up @@ -267,10 +268,7 @@ func setupBootstrapOverride(bootstrapFileMap map[string]string) func() {
}
return nil, os.ErrNotExist
}
return func() {
bootstrapFileReadFunc = oldFileReadFunc
os.Unsetenv(bootstrapFileEnv)
}
return func() { bootstrapFileReadFunc = oldFileReadFunc }
}

// TODO: enable leak check for this package when
Expand Down Expand Up @@ -336,9 +334,10 @@ func TestNewConfigV2ProtoFailure(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := os.Setenv(bootstrapFileEnv, test.name); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", bootstrapFileEnv, test.name, err)
}
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = test.name
defer func() { env.BootstrapFileName = origBootstrapFileName }()

if _, err := NewConfig(); err == nil {
t.Fatalf("NewConfig() returned nil error, expected to fail")
}
Expand Down Expand Up @@ -379,9 +378,10 @@ func TestNewConfigV2ProtoSuccess(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := os.Setenv(bootstrapFileEnv, test.name); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", bootstrapFileEnv, test.name, err)
}
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = test.name
defer func() { env.BootstrapFileName = origBootstrapFileName }()

c, err := NewConfig()
if err != nil {
t.Fatalf("NewConfig() failed: %v", err)
Expand All @@ -398,10 +398,9 @@ func TestNewConfigV2ProtoSuccess(t *testing.T) {
// on the client. In this case, whether the server supports v3 or not, the
// client will end up using v2.
func TestNewConfigV3SupportNotEnabledOnClient(t *testing.T) {
if err := os.Setenv(v3SupportEnv, "false"); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", v3SupportEnv, "true", err)
}
defer os.Unsetenv(v3SupportEnv)
origV3Support := env.V3Support
env.V3Support = false
defer func() { env.V3Support = origV3Support }()

cancel := setupBootstrapOverride(v3BootstrapFileMap)
defer cancel()
Expand All @@ -416,9 +415,10 @@ func TestNewConfigV3SupportNotEnabledOnClient(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := os.Setenv(bootstrapFileEnv, test.name); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", bootstrapFileEnv, test.name, err)
}
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = test.name
defer func() { env.BootstrapFileName = origBootstrapFileName }()

c, err := NewConfig()
if err != nil {
t.Fatalf("NewConfig() failed: %v", err)
Expand All @@ -435,10 +435,9 @@ func TestNewConfigV3SupportNotEnabledOnClient(t *testing.T) {
// client. Here the client ends up using v2 or v3 based on what the server
// supports.
func TestNewConfigV3SupportEnabledOnClient(t *testing.T) {
if err := os.Setenv(v3SupportEnv, "true"); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", v3SupportEnv, "true", err)
}
defer os.Unsetenv(v3SupportEnv)
origV3Support := env.V3Support
env.V3Support = true
defer func() { env.V3Support = origV3Support }()

cancel := setupBootstrapOverride(v3BootstrapFileMap)
defer cancel()
Expand All @@ -453,9 +452,10 @@ func TestNewConfigV3SupportEnabledOnClient(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := os.Setenv(bootstrapFileEnv, test.name); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", bootstrapFileEnv, test.name, err)
}
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = test.name
defer func() { env.BootstrapFileName = origBootstrapFileName }()

c, err := NewConfig()
if err != nil {
t.Fatalf("NewConfig() failed: %v", err)
Expand All @@ -470,7 +470,10 @@ func TestNewConfigV3SupportEnabledOnClient(t *testing.T) {
// TestNewConfigBootstrapFileEnvNotSet tests the case where the bootstrap file
// environment variable is not set.
func TestNewConfigBootstrapFileEnvNotSet(t *testing.T) {
os.Unsetenv(bootstrapFileEnv)
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = ""
defer func() { env.BootstrapFileName = origBootstrapFileName }()

if _, err := NewConfig(); err == nil {
t.Errorf("NewConfig() returned nil error, expected to fail")
}
Expand Down Expand Up @@ -637,10 +640,9 @@ func TestNewConfigWithCertificateProviders(t *testing.T) {
t.Fatalf("config parsing for plugin %q failed: %v", fakeCertProviderName, err)
}

if err := os.Setenv(v3SupportEnv, "true"); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", v3SupportEnv, "true", err)
}
defer os.Unsetenv(v3SupportEnv)
origV3Support := env.V3Support
env.V3Support = true
defer func() { env.V3Support = origV3Support }()

cancel := setupBootstrapOverride(bootstrapFileMap)
defer cancel()
Expand Down Expand Up @@ -684,9 +686,10 @@ func TestNewConfigWithCertificateProviders(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := os.Setenv(bootstrapFileEnv, test.name); err != nil {
t.Fatalf("os.Setenv(%s, %s) failed with error: %v", bootstrapFileEnv, test.name, err)
}
origBootstrapFileName := env.BootstrapFileName
env.BootstrapFileName = test.name
defer func() { env.BootstrapFileName = origBootstrapFileName }()

c, err := NewConfig()
if (err != nil) != test.wantErr {
t.Fatalf("NewConfig() returned: (%+v, %v), wantErr: %v", c.CertProviderConfigs, err, test.wantErr)
Expand Down
42 changes: 42 additions & 0 deletions xds/internal/env/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package env acts a single source of definition for all environment variables
// related to the xDS implementation in gRPC.
package env

import (
"os"
"strings"
)

const (
bootstrapFileNameEnv = "GRPC_XDS_BOOTSTRAP"
xdsV3SupportEnv = "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT"
)

var (
// BootstrapFileName holds the name of the file which contains xDS bootstrap
// configuration. Users can specify the location of the bootstrap file by
// setting the environment variable "GRPC_XDS_BOOSTRAP".
BootstrapFileName = os.Getenv(bootstrapFileNameEnv)
// V3Support indicates whether xDS v3 API support is enabled, which can be
// done by setting the environment variable
// "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT" to "true".
V3Support = strings.EqualFold(os.Getenv(xdsV3SupportEnv), "true")
)

0 comments on commit ea89aca

Please sign in to comment.