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 }