github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/hypervisor/metadatad/httpHandler.go (about)

     1  package metadatad
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	"sort"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/Cloud-Foundations/Dominator/lib/json"
    14  	proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor"
    15  )
    16  
    17  func (s *server) computePaths() {
    18  	s.paths = make(map[string]struct{})
    19  	for path := range s.infoHandlers {
    20  		s.paths[path] = struct{}{}
    21  	}
    22  	for path := range s.rawHandlers {
    23  		s.paths[path] = struct{}{}
    24  	}
    25  }
    26  
    27  func (s *server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    28  	hostname, _, err := net.SplitHostPort(req.RemoteAddr)
    29  	if err != nil {
    30  		fmt.Fprintln(w, err)
    31  		return
    32  	}
    33  	ipAddr := net.ParseIP(hostname)
    34  	s.manager.NotifyVmMetadataRequest(ipAddr, req.URL.Path)
    35  	vmInfo, err := s.manager.GetVmInfo(ipAddr)
    36  	if err != nil {
    37  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    38  		w.WriteHeader(http.StatusNotFound)
    39  		return
    40  	}
    41  	if rawHandler, ok := s.rawHandlers[req.URL.Path]; ok {
    42  		rawHandler(w, ipAddr)
    43  		return
    44  	}
    45  	writer := bufio.NewWriter(w)
    46  	defer writer.Flush()
    47  	if infoHandler, ok := s.infoHandlers[req.URL.Path]; ok {
    48  		if err := infoHandler(writer, vmInfo); err != nil {
    49  			fmt.Fprintln(writer, err)
    50  		}
    51  		return
    52  	}
    53  	paths := make([]string, 0)
    54  	pathsSet := make(map[string]struct{})
    55  	for path := range s.paths {
    56  		if strings.HasPrefix(path, req.URL.Path) {
    57  			splitPath := strings.Split(path[len(req.URL.Path):], "/")
    58  			result := splitPath[0]
    59  			if result == "" {
    60  				result = splitPath[1]
    61  			}
    62  			if _, ok := pathsSet[result]; !ok {
    63  				pathsSet[result] = struct{}{}
    64  				paths = append(paths, result)
    65  			}
    66  		}
    67  	}
    68  	if len(paths) < 1 {
    69  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    70  		w.WriteHeader(http.StatusNotFound)
    71  		return
    72  	}
    73  	sort.Strings(paths)
    74  	for _, path := range paths {
    75  		fmt.Fprintln(writer, path)
    76  	}
    77  }
    78  
    79  func (s *server) showTime(writer io.Writer, vmInfo proto.VmInfo) error {
    80  	now := time.Now()
    81  	nano := now.UnixNano() - now.Unix()*1000000000
    82  	_, err := fmt.Fprintf(writer, "%d.%09d\n", now.Unix(), nano)
    83  	return err
    84  }
    85  
    86  func (s *server) showVM(writer io.Writer, vmInfo proto.VmInfo) error {
    87  	return json.WriteWithIndent(writer, "    ", vmInfo)
    88  }
    89  
    90  func (s *server) showTrue(w http.ResponseWriter, ipAddr net.IP) {
    91  	w.Write([]byte("true\n"))
    92  }
    93  
    94  func (s *server) showUserData(w http.ResponseWriter, ipAddr net.IP) {
    95  	if file, err := s.manager.GetVmUserData(ipAddr); err != nil {
    96  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    97  		w.WriteHeader(http.StatusNotFound)
    98  	} else {
    99  		defer file.Close()
   100  		writer := bufio.NewWriter(w)
   101  		defer writer.Flush()
   102  		io.Copy(writer, file)
   103  	}
   104  }