github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/gcloud/compute_metadata.go (about)

     1  // (c) Copyright IBM Corp. 2021
     2  // (c) Copyright Instana Inc. 2020
     3  
     4  package gcloud
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net/http"
    11  )
    12  
    13  // ProjectMetadata represents Google Cloud project metadata returned by /computeMetadata/v1/project endpoint.
    14  //
    15  // See https://cloud.google.com/compute/docs/storing-retrieving-metadata for further details.
    16  type ProjectMetadata struct {
    17  	ProjectID        string `json:"projectId"`
    18  	NumericProjectID int    `json:"numericProjectId"`
    19  }
    20  
    21  // InstanceMetadata represents Google Cloud project metadata returned by /computeMetadata/v1/instance endpoint.
    22  //
    23  // See https://cloud.google.com/compute/docs/storing-retrieving-metadata for further details.
    24  type InstanceMetadata struct {
    25  	ID     string `json:"id"`
    26  	Region string `json:"region"`
    27  }
    28  
    29  // ComputeMetadata represents Google Cloud project metadata returned by /computeMetadata/v1 endpoint.
    30  //
    31  // See https://cloud.google.com/compute/docs/storing-retrieving-metadata for further details.
    32  type ComputeMetadata struct {
    33  	Project  ProjectMetadata  `json:"project"`
    34  	Instance InstanceMetadata `json:"instance"`
    35  }
    36  
    37  // ComputeMetadataProvider retireves Google Cloud service compute metadata from provided endpoint
    38  type ComputeMetadataProvider struct {
    39  	Endpoint string
    40  	client   *http.Client
    41  }
    42  
    43  // NewComputeMetadataProvider initializes a new ComputeMetadataClient with given endpoint and HTTP client.
    44  // If there is no HTTP client provided, the provider will use http.DefaultClient
    45  func NewComputeMetadataProvider(endpoint string, c *http.Client) *ComputeMetadataProvider {
    46  	if c == nil {
    47  		c = http.DefaultClient
    48  	}
    49  
    50  	return &ComputeMetadataProvider{
    51  		Endpoint: endpoint,
    52  		client:   c,
    53  	}
    54  }
    55  
    56  // ComputeMetadata returns compute metadata for current instance
    57  func (p *ComputeMetadataProvider) ComputeMetadata(ctx context.Context) (ComputeMetadata, error) {
    58  	var data ComputeMetadata
    59  
    60  	req, err := http.NewRequest(http.MethodGet, p.Endpoint+"/computeMetadata/v1?recursive=true", nil)
    61  	if err != nil {
    62  		return data, fmt.Errorf("failed to prepare request: %s", err)
    63  	}
    64  
    65  	req.Header.Set("Metadata-Flavor", "Google")
    66  
    67  	resp, err := p.client.Do(req)
    68  	if err != nil {
    69  		return data, fmt.Errorf("failed to fetch compute metadata: %s", err)
    70  	}
    71  	defer resp.Body.Close()
    72  
    73  	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
    74  		return data, fmt.Errorf("malformed compute metadata response: %s", err)
    75  	}
    76  
    77  	return data, nil
    78  }