github.com/cilium/cilium@v1.16.2/pkg/azure/api/metadata.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package api
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net/http"
    10  	"time"
    11  
    12  	"github.com/cilium/cilium/pkg/safeio"
    13  )
    14  
    15  const (
    16  	metadataURL = "http://169.254.169.254/metadata"
    17  	// current version of the metadata/instance service
    18  	metadataAPIVersion = "2019-06-01"
    19  )
    20  
    21  // GetSubscriptionID retrieves the Azure subscriptionID from the Azure Instance Metadata Service
    22  func GetSubscriptionID(ctx context.Context) (string, error) {
    23  	return getMetadataString(ctx, "instance/compute/subscriptionId")
    24  }
    25  
    26  // GetResourceGroupName retrieves the current resource group name in which the host running the Cilium Operator is located
    27  // This is retrieved via the Azure Instance Metadata Service
    28  func GetResourceGroupName(ctx context.Context) (string, error) {
    29  	return getMetadataString(ctx, "instance/compute/resourceGroupName")
    30  }
    31  
    32  // GetAzureCloudName retrieves the current Azure cloud name in which the host running the Cilium Operator is located
    33  // This is retrieved via the Azure Instance Metadata Service
    34  func GetAzureCloudName(ctx context.Context) (string, error) {
    35  	return getMetadataString(ctx, "instance/compute/azEnvironment")
    36  }
    37  
    38  // getMetadataString returns the text representation of a field from the Azure IMS (instance metadata service)
    39  // more can be found at https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service#instance-api
    40  func getMetadataString(ctx context.Context, path string) (string, error) {
    41  	client := &http.Client{
    42  		Timeout: time.Second * 10,
    43  	}
    44  	url := fmt.Sprintf("%s/%s", metadataURL, path)
    45  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    46  	if err != nil {
    47  		return "", nil
    48  	}
    49  
    50  	query := req.URL.Query()
    51  	query.Add("api-version", metadataAPIVersion)
    52  	query.Add("format", "text")
    53  
    54  	req.URL.RawQuery = query.Encode()
    55  	req.Header.Add("Metadata", "true")
    56  
    57  	resp, err := client.Do(req)
    58  	if err != nil {
    59  		return "", err
    60  	}
    61  	defer func() {
    62  		if err := resp.Body.Close(); err != nil {
    63  			log.WithError(err).Errorf("Failed to close body for request %s", url)
    64  		}
    65  	}()
    66  
    67  	respBytes, err := safeio.ReadAllLimit(resp.Body, safeio.MB)
    68  	if err != nil {
    69  		return "", err
    70  	}
    71  
    72  	return string(respBytes), nil
    73  }