github.com/zhizhiboom/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/client/fingerprint/env_gce_test.go (about)

     1  package fingerprint
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/nomad/client/config"
    13  	cstructs "github.com/hashicorp/nomad/client/structs"
    14  	"github.com/hashicorp/nomad/helper/testlog"
    15  	"github.com/hashicorp/nomad/nomad/structs"
    16  )
    17  
    18  func TestGCEFingerprint_nonGCE(t *testing.T) {
    19  	os.Setenv("GCE_ENV_URL", "http://127.0.0.1/computeMetadata/v1/instance/")
    20  	f := NewEnvGCEFingerprint(testlog.Logger(t))
    21  	node := &structs.Node{
    22  		Attributes: make(map[string]string),
    23  	}
    24  
    25  	request := &cstructs.FingerprintRequest{Config: &config.Config{}, Node: node}
    26  	var response cstructs.FingerprintResponse
    27  	err := f.Fingerprint(request, &response)
    28  	if err != nil {
    29  		t.Fatalf("err: %v", err)
    30  	}
    31  
    32  	if response.Detected {
    33  		t.Fatalf("expected response to not be applicable")
    34  	}
    35  
    36  	if len(response.Attributes) > 0 {
    37  		t.Fatalf("Should have zero attributes without test server")
    38  	}
    39  }
    40  
    41  func testFingerprint_GCE(t *testing.T, withExternalIp bool) {
    42  	node := &structs.Node{
    43  		Attributes: make(map[string]string),
    44  	}
    45  
    46  	// configure mock server with fixture routes, data
    47  	routes := routes{}
    48  	if err := json.Unmarshal([]byte(GCE_routes), &routes); err != nil {
    49  		t.Fatalf("Failed to unmarshal JSON in GCE ENV test: %s", err)
    50  	}
    51  	networkEndpoint := &endpoint{
    52  		Uri:         "/computeMetadata/v1/instance/network-interfaces/?recursive=true",
    53  		ContentType: "application/json",
    54  	}
    55  	if withExternalIp {
    56  		networkEndpoint.Body = `[{"accessConfigs":[{"externalIp":"104.44.55.66","type":"ONE_TO_ONE_NAT"},{"externalIp":"104.44.55.67","type":"ONE_TO_ONE_NAT"}],"forwardedIps":[],"ip":"10.240.0.5","network":"projects/555555/networks/default"}]`
    57  	} else {
    58  		networkEndpoint.Body = `[{"accessConfigs":[],"forwardedIps":[],"ip":"10.240.0.5","network":"projects/555555/networks/default"}]`
    59  	}
    60  	routes.Endpoints = append(routes.Endpoints, networkEndpoint)
    61  
    62  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    63  		value, ok := r.Header["Metadata-Flavor"]
    64  		if !ok {
    65  			t.Fatal("Metadata-Flavor not present in HTTP request header")
    66  		}
    67  		if value[0] != "Google" {
    68  			t.Fatalf("Expected Metadata-Flavor Google, saw %s", value[0])
    69  		}
    70  
    71  		uavalue, ok := r.Header["User-Agent"]
    72  		if !ok {
    73  			t.Fatal("User-Agent not present in HTTP request header")
    74  		}
    75  		if !strings.Contains(uavalue[0], "Nomad/") {
    76  			t.Fatalf("Expected User-Agent to contain Nomad/, got %s", uavalue[0])
    77  		}
    78  
    79  		found := false
    80  		for _, e := range routes.Endpoints {
    81  			if r.RequestURI == e.Uri {
    82  				w.Header().Set("Content-Type", e.ContentType)
    83  				fmt.Fprintln(w, e.Body)
    84  			}
    85  			found = true
    86  		}
    87  
    88  		if !found {
    89  			w.WriteHeader(404)
    90  		}
    91  	}))
    92  	defer ts.Close()
    93  	os.Setenv("GCE_ENV_URL", ts.URL+"/computeMetadata/v1/instance/")
    94  	f := NewEnvGCEFingerprint(testlog.Logger(t))
    95  
    96  	request := &cstructs.FingerprintRequest{Config: &config.Config{}, Node: node}
    97  	var response cstructs.FingerprintResponse
    98  	err := f.Fingerprint(request, &response)
    99  	if err != nil {
   100  		t.Fatalf("err: %v", err)
   101  	}
   102  
   103  	if !response.Detected {
   104  		t.Fatalf("expected response to be applicable")
   105  	}
   106  
   107  	keys := []string{
   108  		"unique.platform.gce.id",
   109  		"unique.platform.gce.hostname",
   110  		"platform.gce.zone",
   111  		"platform.gce.machine-type",
   112  		"platform.gce.zone",
   113  		"platform.gce.tag.abc",
   114  		"platform.gce.tag.def",
   115  		"unique.platform.gce.tag.foo",
   116  		"platform.gce.attr.ghi",
   117  		"platform.gce.attr.jkl",
   118  		"unique.platform.gce.attr.bar",
   119  	}
   120  
   121  	for _, k := range keys {
   122  		assertNodeAttributeContains(t, response.Attributes, k)
   123  	}
   124  
   125  	if len(response.Links) == 0 {
   126  		t.Fatalf("Empty links for Node in GCE Fingerprint test")
   127  	}
   128  
   129  	// Make sure Links contains the GCE ID.
   130  	for _, k := range []string{"gce"} {
   131  		assertNodeLinksContains(t, response.Links, k)
   132  	}
   133  
   134  	assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.id", "12345")
   135  	assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.hostname", "instance-1.c.project.internal")
   136  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.zone", "us-central1-f")
   137  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.machine-type", "n1-standard-1")
   138  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.network.default", "true")
   139  	assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.network.default.ip", "10.240.0.5")
   140  	if withExternalIp {
   141  		assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.network.default.external-ip.0", "104.44.55.66")
   142  		assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.network.default.external-ip.1", "104.44.55.67")
   143  	} else if _, ok := response.Attributes["unique.platform.gce.network.default.external-ip.0"]; ok {
   144  		t.Fatal("unique.platform.gce.network.default.external-ip is set without an external IP")
   145  	}
   146  
   147  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.scheduling.automatic-restart", "TRUE")
   148  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.scheduling.on-host-maintenance", "MIGRATE")
   149  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.cpu-platform", "Intel Ivy Bridge")
   150  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.tag.abc", "true")
   151  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.tag.def", "true")
   152  	assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.tag.foo", "true")
   153  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.attr.ghi", "111")
   154  	assertNodeAttributeEquals(t, response.Attributes, "platform.gce.attr.jkl", "222")
   155  	assertNodeAttributeEquals(t, response.Attributes, "unique.platform.gce.attr.bar", "333")
   156  }
   157  
   158  const GCE_routes = `
   159  {
   160    "endpoints": [
   161      {
   162        "uri": "/computeMetadata/v1/instance/id",
   163        "content-type": "text/plain",
   164        "body": "12345"
   165      },
   166      {
   167        "uri": "/computeMetadata/v1/instance/hostname",
   168        "content-type": "text/plain",
   169        "body": "instance-1.c.project.internal"
   170      },
   171      {
   172        "uri": "/computeMetadata/v1/instance/zone",
   173        "content-type": "text/plain",
   174        "body": "projects/555555/zones/us-central1-f"
   175      },
   176      {
   177        "uri": "/computeMetadata/v1/instance/machine-type",
   178        "content-type": "text/plain",
   179        "body": "projects/555555/machineTypes/n1-standard-1"
   180      },
   181      {
   182        "uri": "/computeMetadata/v1/instance/tags",
   183        "content-type": "application/json",
   184        "body": "[\"abc\", \"def\", \"unique.foo\"]"
   185      },
   186      {
   187        "uri": "/computeMetadata/v1/instance/attributes/?recursive=true",
   188        "content-type": "application/json",
   189        "body": "{\"ghi\":\"111\",\"jkl\":\"222\",\"unique.bar\":\"333\"}"
   190      },
   191      {
   192        "uri": "/computeMetadata/v1/instance/scheduling/automatic-restart",
   193        "content-type": "text/plain",
   194        "body": "TRUE"
   195      },
   196      {
   197        "uri": "/computeMetadata/v1/instance/scheduling/on-host-maintenance",
   198        "content-type": "text/plain",
   199        "body": "MIGRATE"
   200      },
   201      {
   202        "uri": "/computeMetadata/v1/instance/cpu-platform",
   203        "content-type": "text/plain",
   204        "body": "Intel Ivy Bridge"
   205      }
   206    ]
   207  }
   208  `
   209  
   210  func TestFingerprint_GCEWithExternalIp(t *testing.T) {
   211  	testFingerprint_GCE(t, true)
   212  }
   213  
   214  func TestFingerprint_GCEWithoutExternalIp(t *testing.T) {
   215  	testFingerprint_GCE(t, false)
   216  }