google.golang.org/grpc@v1.62.1/internal/testutils/xds/bootstrap/bootstrap.go (about) 1 /* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package bootstrap provides functionality to generate bootstrap configuration. 20 package bootstrap 21 22 import ( 23 "encoding/json" 24 "fmt" 25 "os" 26 27 "google.golang.org/grpc/grpclog" 28 "google.golang.org/grpc/internal/envconfig" 29 ) 30 31 var logger = grpclog.Component("internal/xds") 32 33 // Options wraps the parameters used to generate bootstrap configuration. 34 type Options struct { 35 // NodeID is the node identifier of the gRPC client/server node in the 36 // proxyless service mesh. 37 NodeID string 38 // ServerURI is the address of the management server. 39 ServerURI string 40 // IgnoreResourceDeletion, if true, results in a bootstrap config with the 41 // `server_features` list containing `ignore_resource_deletion`. This results 42 // in gRPC ignoring resource deletions from the management server, as per A53. 43 IgnoreResourceDeletion bool 44 // ClientDefaultListenerResourceNameTemplate is the default listener 45 // resource name template to be used on the gRPC client. 46 ClientDefaultListenerResourceNameTemplate string 47 // ServerListenerResourceNameTemplate is the listener resource name template 48 // to be used on the gRPC server. 49 ServerListenerResourceNameTemplate string 50 // CertificateProviders is the certificate providers configuration. 51 CertificateProviders map[string]json.RawMessage 52 // Authorities is a list of non-default authorities. 53 // 54 // In the config, an authority contains {ServerURI, xds-version, creds, 55 // features, etc}. Note that this fields only has ServerURI (it's a 56 // map[authority-name]ServerURI). The other fields (version, creds, 57 // features) are assumed to be the same as the default authority (they can 58 // be added later if needed). 59 // 60 // If the env var corresponding to federation (envconfig.XDSFederation) is 61 // set, an entry with empty string as the key and empty server config as 62 // value will be added. This will be used by new style resource names with 63 // an empty authority. 64 Authorities map[string]string 65 } 66 67 // CreateFile creates a temporary file with bootstrap contents, based on the 68 // passed in options, and updates the bootstrap environment variable to point to 69 // this file. 70 // 71 // Returns a cleanup function which will be non-nil if the setup process was 72 // completed successfully. It is the responsibility of the caller to invoke the 73 // cleanup function at the end of the test. 74 func CreateFile(opts Options) (func(), error) { 75 bootstrapContents, err := Contents(opts) 76 if err != nil { 77 return nil, err 78 } 79 f, err := os.CreateTemp("", "test_xds_bootstrap_*") 80 if err != nil { 81 return nil, fmt.Errorf("failed to created bootstrap file: %v", err) 82 } 83 84 if err := os.WriteFile(f.Name(), bootstrapContents, 0644); err != nil { 85 return nil, fmt.Errorf("failed to created bootstrap file: %v", err) 86 } 87 logger.Infof("Created bootstrap file at %q with contents: %s\n", f.Name(), bootstrapContents) 88 89 origBootstrapFileName := envconfig.XDSBootstrapFileName 90 envconfig.XDSBootstrapFileName = f.Name() 91 return func() { 92 os.Remove(f.Name()) 93 envconfig.XDSBootstrapFileName = origBootstrapFileName 94 }, nil 95 } 96 97 // Contents returns the contents to go into a bootstrap file, environment, or 98 // configuration passed to xds.NewXDSResolverWithConfigForTesting. 99 func Contents(opts Options) ([]byte, error) { 100 cfg := &bootstrapConfig{ 101 XdsServers: []server{ 102 { 103 ServerURI: opts.ServerURI, 104 ChannelCreds: []creds{{Type: "insecure"}}, 105 }, 106 }, 107 Node: node{ 108 ID: opts.NodeID, 109 }, 110 CertificateProviders: opts.CertificateProviders, 111 ClientDefaultListenerResourceNameTemplate: opts.ClientDefaultListenerResourceNameTemplate, 112 ServerListenerResourceNameTemplate: opts.ServerListenerResourceNameTemplate, 113 } 114 cfg.XdsServers[0].ServerFeatures = append(cfg.XdsServers[0].ServerFeatures, "xds_v3") 115 if opts.IgnoreResourceDeletion { 116 cfg.XdsServers[0].ServerFeatures = append(cfg.XdsServers[0].ServerFeatures, "ignore_resource_deletion") 117 } 118 119 // This will end up using the top-level server list for new style 120 // resources with empty authority. 121 auths := map[string]authority{"": {}} 122 for n, auURI := range opts.Authorities { 123 auths[n] = authority{XdsServers: []server{{ 124 ServerURI: auURI, 125 ChannelCreds: []creds{{Type: "insecure"}}, 126 ServerFeatures: cfg.XdsServers[0].ServerFeatures, 127 }}} 128 } 129 cfg.Authorities = auths 130 131 bootstrapContents, err := json.MarshalIndent(cfg, "", " ") 132 if err != nil { 133 return nil, fmt.Errorf("failed to created bootstrap file: %v", err) 134 } 135 return bootstrapContents, nil 136 } 137 138 type bootstrapConfig struct { 139 XdsServers []server `json:"xds_servers,omitempty"` 140 Node node `json:"node,omitempty"` 141 CertificateProviders map[string]json.RawMessage `json:"certificate_providers,omitempty"` 142 ClientDefaultListenerResourceNameTemplate string `json:"client_default_listener_resource_name_template,omitempty"` 143 ServerListenerResourceNameTemplate string `json:"server_listener_resource_name_template,omitempty"` 144 Authorities map[string]authority `json:"authorities,omitempty"` 145 } 146 147 type authority struct { 148 XdsServers []server `json:"xds_servers,omitempty"` 149 } 150 151 type server struct { 152 ServerURI string `json:"server_uri,omitempty"` 153 ChannelCreds []creds `json:"channel_creds,omitempty"` 154 ServerFeatures []string `json:"server_features,omitempty"` 155 } 156 157 type creds struct { 158 Type string `json:"type,omitempty"` 159 Config any `json:"config,omitempty"` 160 } 161 162 type node struct { 163 ID string `json:"id,omitempty"` 164 }