istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/fakes/gce_metadata_server/main.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "fmt" 20 "log" 21 "net/http" 22 "os" 23 "os/signal" 24 "syscall" 25 26 "github.com/gorilla/mux" 27 ) 28 29 const ( 30 projID = "test-project" 31 projNumber = "123456789" 32 instance = "test-instance" 33 instID = "987654321" 34 zone = "us-west1-c" 35 36 metaPrefix = "/computeMetadata/v1" 37 projIDPath = metaPrefix + "/project/project-id" 38 projNumberPath = metaPrefix + "/project/numeric-project-id" 39 instIDPath = metaPrefix + "/instance/id" 40 instancePath = metaPrefix + "/instance/name" 41 zonePath = metaPrefix + "/instance/zone" 42 attrKey = "attribute" 43 attrPath = metaPrefix + "/instance/attributes/{" + attrKey + "}" 44 ) 45 46 var instAttrs = map[string]string{ 47 "instance-template": "some-template", 48 "created-by": "some-creator", 49 "cluster-name": "test-cluster", 50 } 51 52 var vmInstAttrs = map[string]string{ 53 "instance-template": "some-template", 54 "created-by": "some-creator", 55 } 56 57 func checkMetadataHeaders(next http.Handler) http.Handler { 58 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 59 log.Println("request for: " + r.URL.Path) 60 w.Header().Add("Server", "Metadata Server for VM (Fake)") 61 w.Header().Add("Metadata-Flavor", "Google") 62 63 flavor := r.Header.Get("Metadata-Flavor") 64 if flavor == "" && r.RequestURI != "/" { 65 http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) 66 w.Header().Set("Content-Type", "text/html; charset=UTF-8") 67 log.Println("forbidden: " + r.URL.Path) 68 return 69 } 70 71 next.ServeHTTP(w, r) 72 }) 73 } 74 75 func handleAttrs(attrs map[string]string) func(w http.ResponseWriter, r *http.Request) { 76 return func(w http.ResponseWriter, r *http.Request) { 77 vars := mux.Vars(r) 78 79 if val, ok := attrs[vars[attrKey]]; ok { 80 fmt.Fprint(w, val) 81 return 82 } 83 84 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 85 } 86 } 87 88 func main() { 89 s1 := runServer(":8080", instAttrs) 90 s2 := runServer(":8081", vmInstAttrs) 91 done := make(chan os.Signal, 1) 92 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 93 log.Println("GCE metadata server started") 94 <-done 95 if err := s1.Shutdown(context.Background()); err != nil { 96 log.Fatalf("GCE Metadata Shutdown Failed: %+v", err) 97 } 98 if err := s2.Shutdown(context.Background()); err != nil { 99 log.Fatalf("GCE Metadata Shutdown Failed: %+v", err) 100 } 101 } 102 103 func runServer(addr string, attrs map[string]string) *http.Server { 104 r := mux.NewRouter() 105 r.Use(checkMetadataHeaders) 106 r.HandleFunc(projIDPath, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, projID) }).Methods("GET") 107 r.HandleFunc(projNumberPath, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, projNumber) }).Methods("GET") 108 r.HandleFunc(instIDPath, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, instID) }).Methods("GET") 109 r.HandleFunc(instancePath, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, instance) }).Methods("GET") 110 r.HandleFunc(zonePath, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, zone) }).Methods("GET") 111 r.HandleFunc(attrPath, handleAttrs(attrs)).Methods("GET") 112 113 srv := &http.Server{Addr: addr, Handler: r} 114 115 go func() { 116 if err := srv.ListenAndServe(); err != http.ErrServerClosed { 117 log.Fatalf("listen: %v\n", err) 118 } 119 }() 120 return srv 121 }