github.com/manicqin/nomad@v0.9.5/client/fingerprint/env_aws_test.go (about)

     1  package fingerprint
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/nomad/client/config"
    11  	"github.com/hashicorp/nomad/helper/testlog"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestEnvAWSFingerprint_nonAws(t *testing.T) {
    17  	f := NewEnvAWSFingerprint(testlog.HCLogger(t))
    18  	f.(*EnvAWSFingerprint).endpoint = "http://127.0.0.1/latest"
    19  
    20  	node := &structs.Node{
    21  		Attributes: make(map[string]string),
    22  	}
    23  
    24  	request := &FingerprintRequest{Config: &config.Config{}, Node: node}
    25  	var response FingerprintResponse
    26  	err := f.Fingerprint(request, &response)
    27  	require.NoError(t, err)
    28  	require.Empty(t, response.Attributes)
    29  }
    30  
    31  func TestEnvAWSFingerprint_aws(t *testing.T) {
    32  	endpoint, cleanup := startFakeEC2Metadata(t)
    33  	defer cleanup()
    34  
    35  	f := NewEnvAWSFingerprint(testlog.HCLogger(t))
    36  	f.(*EnvAWSFingerprint).endpoint = endpoint
    37  
    38  	node := &structs.Node{
    39  		Attributes: make(map[string]string),
    40  	}
    41  
    42  	request := &FingerprintRequest{Config: &config.Config{}, Node: node}
    43  	var response FingerprintResponse
    44  	err := f.Fingerprint(request, &response)
    45  	require.NoError(t, err)
    46  
    47  	keys := []string{
    48  		"platform.aws.ami-id",
    49  		"unique.platform.aws.hostname",
    50  		"unique.platform.aws.instance-id",
    51  		"platform.aws.instance-type",
    52  		"unique.platform.aws.local-hostname",
    53  		"unique.platform.aws.local-ipv4",
    54  		"unique.platform.aws.public-hostname",
    55  		"unique.platform.aws.public-ipv4",
    56  		"platform.aws.placement.availability-zone",
    57  		"unique.network.ip-address",
    58  	}
    59  
    60  	for _, k := range keys {
    61  		assertNodeAttributeContains(t, response.Attributes, k)
    62  	}
    63  
    64  	require.NotEmpty(t, response.Links)
    65  
    66  	// confirm we have at least instance-id and ami-id
    67  	for _, k := range []string{"aws.ec2"} {
    68  		assertNodeLinksContains(t, response.Links, k)
    69  	}
    70  }
    71  
    72  func TestNetworkFingerprint_AWS(t *testing.T) {
    73  	endpoint, cleanup := startFakeEC2Metadata(t)
    74  	defer cleanup()
    75  
    76  	f := NewEnvAWSFingerprint(testlog.HCLogger(t))
    77  	f.(*EnvAWSFingerprint).endpoint = endpoint
    78  
    79  	node := &structs.Node{
    80  		Attributes: make(map[string]string),
    81  	}
    82  
    83  	request := &FingerprintRequest{Config: &config.Config{}, Node: node}
    84  	var response FingerprintResponse
    85  	err := f.Fingerprint(request, &response)
    86  	require.NoError(t, err)
    87  
    88  	assertNodeAttributeContains(t, response.Attributes, "unique.network.ip-address")
    89  
    90  	require.NotNil(t, response.NodeResources)
    91  	require.Len(t, response.NodeResources.Networks, 1)
    92  
    93  	// Test at least the first Network Resource
    94  	net := response.NodeResources.Networks[0]
    95  	require.NotEmpty(t, net.IP, "Expected Network Resource to have an IP")
    96  	require.NotEmpty(t, net.CIDR, "Expected Network Resource to have a CIDR")
    97  	require.NotEmpty(t, net.Device, "Expected Network Resource to have a Device Name")
    98  }
    99  
   100  func TestNetworkFingerprint_AWS_network(t *testing.T) {
   101  	endpoint, cleanup := startFakeEC2Metadata(t)
   102  	defer cleanup()
   103  
   104  	f := NewEnvAWSFingerprint(testlog.HCLogger(t))
   105  	f.(*EnvAWSFingerprint).endpoint = endpoint
   106  
   107  	{
   108  		node := &structs.Node{
   109  			Attributes: make(map[string]string),
   110  		}
   111  
   112  		request := &FingerprintRequest{Config: &config.Config{}, Node: node}
   113  		var response FingerprintResponse
   114  		err := f.Fingerprint(request, &response)
   115  		require.NoError(t, err)
   116  
   117  		require.True(t, response.Detected, "expected response to be applicable")
   118  
   119  		assertNodeAttributeContains(t, response.Attributes, "unique.network.ip-address")
   120  
   121  		require.NotNil(t, response.NodeResources)
   122  		require.Len(t, response.NodeResources.Networks, 1)
   123  
   124  		// Test at least the first Network Resource
   125  		net := response.NodeResources.Networks[0]
   126  		require.NotEmpty(t, net.IP, "Expected Network Resource to have an IP")
   127  		require.NotEmpty(t, net.CIDR, "Expected Network Resource to have a CIDR")
   128  		require.NotEmpty(t, net.Device, "Expected Network Resource to have a Device Name")
   129  		require.Equal(t, 1000, net.MBits)
   130  	}
   131  
   132  	// Try again this time setting a network speed in the config
   133  	{
   134  		node := &structs.Node{
   135  			Attributes: make(map[string]string),
   136  		}
   137  
   138  		cfg := &config.Config{
   139  			NetworkSpeed: 10,
   140  		}
   141  
   142  		request := &FingerprintRequest{Config: cfg, Node: node}
   143  		var response FingerprintResponse
   144  		err := f.Fingerprint(request, &response)
   145  		require.NoError(t, err)
   146  
   147  		assertNodeAttributeContains(t, response.Attributes, "unique.network.ip-address")
   148  
   149  		require.NotNil(t, response.NodeResources)
   150  		require.Len(t, response.NodeResources.Networks, 1)
   151  
   152  		// Test at least the first Network Resource
   153  		net := response.NodeResources.Networks[0]
   154  		require.NotEmpty(t, net.IP, "Expected Network Resource to have an IP")
   155  		require.NotEmpty(t, net.CIDR, "Expected Network Resource to have a CIDR")
   156  		require.NotEmpty(t, net.Device, "Expected Network Resource to have a Device Name")
   157  		require.Equal(t, 10, net.MBits)
   158  	}
   159  }
   160  
   161  /// Utility functions for tests
   162  
   163  func startFakeEC2Metadata(t *testing.T) (endpoint string, cleanup func()) {
   164  	routes := routes{}
   165  	if err := json.Unmarshal([]byte(aws_routes), &routes); err != nil {
   166  		t.Fatalf("Failed to unmarshal JSON in AWS ENV test: %s", err)
   167  	}
   168  
   169  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   170  		for _, e := range routes.Endpoints {
   171  			if r.RequestURI == e.Uri {
   172  				w.Header().Set("Content-Type", e.ContentType)
   173  				fmt.Fprintln(w, e.Body)
   174  			}
   175  		}
   176  	}))
   177  
   178  	return ts.URL + "/latest", ts.Close
   179  }
   180  
   181  type routes struct {
   182  	Endpoints []*endpoint `json:"endpoints"`
   183  }
   184  type endpoint struct {
   185  	Uri         string `json:"uri"`
   186  	ContentType string `json:"content-type"`
   187  	Body        string `json:"body"`
   188  }
   189  
   190  const aws_routes = `
   191  {
   192    "endpoints": [
   193      {
   194        "uri": "/latest/meta-data/ami-id",
   195        "content-type": "text/plain",
   196        "body": "ami-1234"
   197      },
   198      {
   199        "uri": "/latest/meta-data/hostname",
   200        "content-type": "text/plain",
   201        "body": "ip-10-0-0-207.us-west-2.compute.internal"
   202      },
   203      {
   204        "uri": "/latest/meta-data/placement/availability-zone",
   205        "content-type": "text/plain",
   206        "body": "us-west-2a"
   207      },
   208      {
   209        "uri": "/latest/meta-data/instance-id",
   210        "content-type": "text/plain",
   211        "body": "i-b3ba3875"
   212      },
   213      {
   214        "uri": "/latest/meta-data/instance-type",
   215        "content-type": "text/plain",
   216        "body": "m3.2xlarge"
   217      },
   218      {
   219        "uri": "/latest/meta-data/local-hostname",
   220        "content-type": "text/plain",
   221        "body": "ip-10-0-0-207.us-west-2.compute.internal"
   222      },
   223      {
   224        "uri": "/latest/meta-data/local-ipv4",
   225        "content-type": "text/plain",
   226        "body": "10.0.0.207"
   227      },
   228      {
   229        "uri": "/latest/meta-data/public-hostname",
   230        "content-type": "text/plain",
   231        "body": "ec2-54-191-117-175.us-west-2.compute.amazonaws.com"
   232      },
   233      {
   234        "uri": "/latest/meta-data/public-ipv4",
   235        "content-type": "text/plain",
   236        "body": "54.191.117.175"
   237      }
   238    ]
   239  }
   240  `