55 "fmt"
66 "io/ioutil"
77 "net/http"
8+ "net/url"
89 "os"
910 "strings"
1011 "sync"
@@ -13,33 +14,41 @@ import (
1314 "google.golang.org/protobuf/types/known/structpb"
1415
1516 "github.com/startdusk/strnaming"
16- ycsdk "github.com/yandex-cloud/go-sdk"
1717)
1818
19- func getMetadataUrl () string {
19+ func getMetadataUrl (instanceMetadataAddr string ) ( * url. URL , error ) {
2020 const (
2121 keyMetadataUrlEnv = "YC_METADATA_URL"
22- urlSuffix = "/computeMetadata/v1/"
22+ urlPath = "/computeMetadata/v1/"
2323 )
2424 metadataEndpoint := os .Getenv (keyMetadataUrlEnv )
2525 if len (metadataEndpoint ) == 0 {
26- metadataEndpoint = "http://" + ycsdk . InstanceMetadataAddr
26+ metadataEndpoint = "http://" + instanceMetadataAddr
2727 }
28- return metadataEndpoint + urlSuffix
28+ urlMetadata , err := url .Parse (metadataEndpoint )
29+ if err != nil {
30+ return nil , err
31+ }
32+ urlMetadata .Path = urlPath
33+ return urlMetadata , nil
2934}
3035
3136type Provider interface {
3237 GetValue (key string ) (string , error )
3338}
3439
3540type cachingProvider struct {
36- mu sync.RWMutex
37- lastUpdate time.Time
38- cache * structpb.Struct
41+ mu sync.RWMutex
42+ instanceMetadataAddr string
43+ lastUpdate time.Time
44+ cache * structpb.Struct
3945}
4046
4147func (mp * cachingProvider ) GetValue (key string ) (string , error ) {
4248 cache , err := mp .getAllMetadata ()
49+ if err != nil {
50+ return "" , fmt .Errorf ("failed to get metadata value by key%q: %s" , key , err .Error ())
51+ }
4352
4453 toCamel := strnaming .NewCamel ()
4554 toCamel .WithDelimiter ('-' )
@@ -48,30 +57,38 @@ func (mp *cachingProvider) GetValue(key string) (string, error) {
4857
4958 value , err := getValue (cache , path )
5059 if err != nil {
51- return "" , fmt .Errorf ("failed to get metadata value by key %q because of error : %s" , key , err .Error ())
60+ return "" , fmt .Errorf ("failed to get metadata value by key %q: %s" , key , err .Error ())
5261 }
5362 return value , nil
5463}
5564
5665func (mp * cachingProvider ) getAllMetadata () (* structpb.Struct , error ) {
57- const updateBackoff = time .Second
66+ const (
67+ updateBackoff = time .Second
68+ queryParamKey = "recursive"
69+ queryParamValue = "true"
70+ requestTimeout = 5 * time .Second
71+ )
72+
5873 mp .mu .RLock ()
74+
5975 passed := time .Since (mp .lastUpdate )
6076 if mp .cache != nil && passed < updateBackoff {
6177 defer mp .mu .RUnlock ()
6278 return mp .cache , nil
6379 }
64- mp .mu .RUnlock ()
65-
66- const (
67- queryParam = "?recursive=true"
68- requestTimeout = 5 * time .Second
69- )
80+ urlMetadata , err := getMetadataUrl (mp .instanceMetadataAddr )
81+ if err != nil {
82+ return nil , fmt .Errorf ("incorrect metadata URL: %s" , err .Error ())
83+ }
84+ q := urlMetadata .Query ()
85+ q .Set (queryParamKey , queryParamValue )
86+ urlMetadata .RawQuery = q .Encode ()
7087
71- urlMetadata := getMetadataUrl () + queryParam
88+ mp . mu . RUnlock ()
7289
7390 client := http.Client {}
74- req , err := http .NewRequest (http .MethodGet , urlMetadata , nil )
91+ req , err := http .NewRequest (http .MethodGet , urlMetadata . String () , nil )
7592 if err != nil {
7693 return nil , fmt .Errorf ("could not make request to get all metadata: %s" , err .Error ())
7794 }
@@ -105,6 +122,8 @@ func (mp *cachingProvider) getAllMetadata() (*structpb.Struct, error) {
105122 return metadataStruct , nil
106123}
107124
108- func NewCachingProvider () Provider {
109- return & cachingProvider {}
125+ func NewCachingProvider (instanceMetadataAddr string ) Provider {
126+ return & cachingProvider {
127+ instanceMetadataAddr : instanceMetadataAddr ,
128+ }
110129}
0 commit comments