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 }