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