github.com/rish1988/moby@v25.0.2+incompatible/libnetwork/networkdb/networkdbdiagnostic.go (about)

     1  package networkdb
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"fmt"
     7  	"net/http"
     8  	"strings"
     9  
    10  	"github.com/containerd/log"
    11  	"github.com/docker/docker/libnetwork/diagnostic"
    12  	"github.com/docker/docker/libnetwork/internal/caller"
    13  )
    14  
    15  const (
    16  	missingParameter = "missing parameter"
    17  	dbNotAvailable   = "database not available"
    18  )
    19  
    20  type Mux interface {
    21  	HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
    22  }
    23  
    24  func (nDB *NetworkDB) RegisterDiagnosticHandlers(m Mux) {
    25  	m.HandleFunc("/join", nDB.dbJoin)
    26  	m.HandleFunc("/networkpeers", nDB.dbPeers)
    27  	m.HandleFunc("/clusterpeers", nDB.dbClusterPeers)
    28  	m.HandleFunc("/joinnetwork", nDB.dbJoinNetwork)
    29  	m.HandleFunc("/leavenetwork", nDB.dbLeaveNetwork)
    30  	m.HandleFunc("/createentry", nDB.dbCreateEntry)
    31  	m.HandleFunc("/updateentry", nDB.dbUpdateEntry)
    32  	m.HandleFunc("/deleteentry", nDB.dbDeleteEntry)
    33  	m.HandleFunc("/getentry", nDB.dbGetEntry)
    34  	m.HandleFunc("/gettable", nDB.dbGetTable)
    35  	m.HandleFunc("/networkstats", nDB.dbNetworkStats)
    36  }
    37  
    38  func (nDB *NetworkDB) dbJoin(w http.ResponseWriter, r *http.Request) {
    39  	_ = r.ParseForm()
    40  	diagnostic.DebugHTTPForm(r)
    41  	_, json := diagnostic.ParseHTTPFormOptions(r)
    42  
    43  	// audit logs
    44  	logger := log.G(context.TODO()).WithFields(log.Fields{
    45  		"component": "diagnostic",
    46  		"remoteIP":  r.RemoteAddr,
    47  		"method":    caller.Name(0),
    48  		"url":       r.URL.String(),
    49  	})
    50  	logger.Info("join cluster")
    51  
    52  	if len(r.Form["members"]) < 1 {
    53  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?members=ip1,ip2,...", r.URL.Path))
    54  		logger.Error("join cluster failed, wrong input")
    55  		diagnostic.HTTPReply(w, rsp, json)
    56  		return
    57  	}
    58  
    59  	err := nDB.Join(strings.Split(r.Form["members"][0], ","))
    60  	if err != nil {
    61  		rsp := diagnostic.FailCommand(fmt.Errorf("%s error in the DB join %s", r.URL.Path, err))
    62  		logger.WithError(err).Error("join cluster failed")
    63  		diagnostic.HTTPReply(w, rsp, json)
    64  		return
    65  	}
    66  
    67  	logger.Info("join cluster done")
    68  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
    69  }
    70  
    71  func (nDB *NetworkDB) dbPeers(w http.ResponseWriter, r *http.Request) {
    72  	_ = r.ParseForm()
    73  	diagnostic.DebugHTTPForm(r)
    74  	_, json := diagnostic.ParseHTTPFormOptions(r)
    75  
    76  	// audit logs
    77  	logger := log.G(context.TODO()).WithFields(log.Fields{
    78  		"component": "diagnostic",
    79  		"remoteIP":  r.RemoteAddr,
    80  		"method":    caller.Name(0),
    81  		"url":       r.URL.String(),
    82  	})
    83  	logger.Info("network peers")
    84  
    85  	if len(r.Form["nid"]) < 1 {
    86  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path))
    87  		logger.Error("network peers failed, wrong input")
    88  		diagnostic.HTTPReply(w, rsp, json)
    89  		return
    90  	}
    91  
    92  	peers := nDB.Peers(r.Form["nid"][0])
    93  	rsp := &diagnostic.TableObj{Length: len(peers)}
    94  	for i, peerInfo := range peers {
    95  		if peerInfo.IP == "unknown" {
    96  			rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: "orphan-" + peerInfo.Name, IP: peerInfo.IP})
    97  		} else {
    98  			rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
    99  		}
   100  	}
   101  	logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network peers done")
   102  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
   103  }
   104  
   105  func (nDB *NetworkDB) dbClusterPeers(w http.ResponseWriter, r *http.Request) {
   106  	_ = r.ParseForm()
   107  	diagnostic.DebugHTTPForm(r)
   108  	_, json := diagnostic.ParseHTTPFormOptions(r)
   109  
   110  	// audit logs
   111  	logger := log.G(context.TODO()).WithFields(log.Fields{
   112  		"component": "diagnostic",
   113  		"remoteIP":  r.RemoteAddr,
   114  		"method":    caller.Name(0),
   115  		"url":       r.URL.String(),
   116  	})
   117  	logger.Info("cluster peers")
   118  
   119  	peers := nDB.ClusterPeers()
   120  	rsp := &diagnostic.TableObj{Length: len(peers)}
   121  	for i, peerInfo := range peers {
   122  		rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
   123  	}
   124  	logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("cluster peers done")
   125  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
   126  }
   127  
   128  func (nDB *NetworkDB) dbCreateEntry(w http.ResponseWriter, r *http.Request) {
   129  	_ = r.ParseForm()
   130  	diagnostic.DebugHTTPForm(r)
   131  	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
   132  
   133  	// audit logs
   134  	logger := log.G(context.TODO()).WithFields(log.Fields{
   135  		"component": "diagnostic",
   136  		"remoteIP":  r.RemoteAddr,
   137  		"method":    caller.Name(0),
   138  		"url":       r.URL.String(),
   139  	})
   140  	logger.Info("create entry")
   141  
   142  	if len(r.Form["tname"]) < 1 ||
   143  		len(r.Form["nid"]) < 1 ||
   144  		len(r.Form["key"]) < 1 ||
   145  		len(r.Form["value"]) < 1 {
   146  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
   147  		logger.Error("create entry failed, wrong input")
   148  		diagnostic.HTTPReply(w, rsp, json)
   149  		return
   150  	}
   151  
   152  	tname := r.Form["tname"][0]
   153  	nid := r.Form["nid"][0]
   154  	key := r.Form["key"][0]
   155  	value := r.Form["value"][0]
   156  	decodedValue := []byte(value)
   157  	if !unsafe {
   158  		var err error
   159  		decodedValue, err = base64.StdEncoding.DecodeString(value)
   160  		if err != nil {
   161  			logger.WithError(err).Error("create entry failed")
   162  			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   163  			return
   164  		}
   165  	}
   166  
   167  	if err := nDB.CreateEntry(tname, nid, key, decodedValue); err != nil {
   168  		rsp := diagnostic.FailCommand(err)
   169  		diagnostic.HTTPReply(w, rsp, json)
   170  		logger.WithError(err).Error("create entry failed")
   171  		return
   172  	}
   173  	logger.Info("create entry done")
   174  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
   175  }
   176  
   177  func (nDB *NetworkDB) dbUpdateEntry(w http.ResponseWriter, r *http.Request) {
   178  	_ = r.ParseForm()
   179  	diagnostic.DebugHTTPForm(r)
   180  	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
   181  
   182  	// audit logs
   183  	logger := log.G(context.TODO()).WithFields(log.Fields{
   184  		"component": "diagnostic",
   185  		"remoteIP":  r.RemoteAddr,
   186  		"method":    caller.Name(0),
   187  		"url":       r.URL.String(),
   188  	})
   189  	logger.Info("update entry")
   190  
   191  	if len(r.Form["tname"]) < 1 ||
   192  		len(r.Form["nid"]) < 1 ||
   193  		len(r.Form["key"]) < 1 ||
   194  		len(r.Form["value"]) < 1 {
   195  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
   196  		logger.Error("update entry failed, wrong input")
   197  		diagnostic.HTTPReply(w, rsp, json)
   198  		return
   199  	}
   200  
   201  	tname := r.Form["tname"][0]
   202  	nid := r.Form["nid"][0]
   203  	key := r.Form["key"][0]
   204  	value := r.Form["value"][0]
   205  	decodedValue := []byte(value)
   206  	if !unsafe {
   207  		var err error
   208  		decodedValue, err = base64.StdEncoding.DecodeString(value)
   209  		if err != nil {
   210  			logger.WithError(err).Error("update entry failed")
   211  			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   212  			return
   213  		}
   214  	}
   215  
   216  	if err := nDB.UpdateEntry(tname, nid, key, decodedValue); err != nil {
   217  		logger.WithError(err).Error("update entry failed")
   218  		diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   219  		return
   220  	}
   221  	logger.Info("update entry done")
   222  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
   223  }
   224  
   225  func (nDB *NetworkDB) dbDeleteEntry(w http.ResponseWriter, r *http.Request) {
   226  	_ = r.ParseForm()
   227  	diagnostic.DebugHTTPForm(r)
   228  	_, json := diagnostic.ParseHTTPFormOptions(r)
   229  
   230  	// audit logs
   231  	logger := log.G(context.TODO()).WithFields(log.Fields{
   232  		"component": "diagnostic",
   233  		"remoteIP":  r.RemoteAddr,
   234  		"method":    caller.Name(0),
   235  		"url":       r.URL.String(),
   236  	})
   237  	logger.Info("delete entry")
   238  
   239  	if len(r.Form["tname"]) < 1 ||
   240  		len(r.Form["nid"]) < 1 ||
   241  		len(r.Form["key"]) < 1 {
   242  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
   243  		logger.Error("delete entry failed, wrong input")
   244  		diagnostic.HTTPReply(w, rsp, json)
   245  		return
   246  	}
   247  
   248  	tname := r.Form["tname"][0]
   249  	nid := r.Form["nid"][0]
   250  	key := r.Form["key"][0]
   251  
   252  	err := nDB.DeleteEntry(tname, nid, key)
   253  	if err != nil {
   254  		logger.WithError(err).Error("delete entry failed")
   255  		diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   256  		return
   257  	}
   258  	logger.Info("delete entry done")
   259  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
   260  }
   261  
   262  func (nDB *NetworkDB) dbGetEntry(w http.ResponseWriter, r *http.Request) {
   263  	_ = r.ParseForm()
   264  	diagnostic.DebugHTTPForm(r)
   265  	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
   266  
   267  	// audit logs
   268  	logger := log.G(context.TODO()).WithFields(log.Fields{
   269  		"component": "diagnostic",
   270  		"remoteIP":  r.RemoteAddr,
   271  		"method":    caller.Name(0),
   272  		"url":       r.URL.String(),
   273  	})
   274  	logger.Info("get entry")
   275  
   276  	if len(r.Form["tname"]) < 1 ||
   277  		len(r.Form["nid"]) < 1 ||
   278  		len(r.Form["key"]) < 1 {
   279  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
   280  		logger.Error("get entry failed, wrong input")
   281  		diagnostic.HTTPReply(w, rsp, json)
   282  		return
   283  	}
   284  
   285  	tname := r.Form["tname"][0]
   286  	nid := r.Form["nid"][0]
   287  	key := r.Form["key"][0]
   288  
   289  	value, err := nDB.GetEntry(tname, nid, key)
   290  	if err != nil {
   291  		logger.WithError(err).Error("get entry failed")
   292  		diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   293  		return
   294  	}
   295  
   296  	var encodedValue string
   297  	if unsafe {
   298  		encodedValue = string(value)
   299  	} else {
   300  		encodedValue = base64.StdEncoding.EncodeToString(value)
   301  	}
   302  
   303  	rsp := &diagnostic.TableEntryObj{Key: key, Value: encodedValue}
   304  	logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get entry done")
   305  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
   306  }
   307  
   308  func (nDB *NetworkDB) dbJoinNetwork(w http.ResponseWriter, r *http.Request) {
   309  	_ = r.ParseForm()
   310  	diagnostic.DebugHTTPForm(r)
   311  	_, json := diagnostic.ParseHTTPFormOptions(r)
   312  
   313  	// audit logs
   314  	logger := log.G(context.TODO()).WithFields(log.Fields{
   315  		"component": "diagnostic",
   316  		"remoteIP":  r.RemoteAddr,
   317  		"method":    caller.Name(0),
   318  		"url":       r.URL.String(),
   319  	})
   320  	logger.Info("join network")
   321  
   322  	if len(r.Form["nid"]) < 1 {
   323  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
   324  		logger.Error("join network failed, wrong input")
   325  		diagnostic.HTTPReply(w, rsp, json)
   326  		return
   327  	}
   328  
   329  	nid := r.Form["nid"][0]
   330  
   331  	if err := nDB.JoinNetwork(nid); err != nil {
   332  		logger.WithError(err).Error("join network failed")
   333  		diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   334  		return
   335  	}
   336  	logger.Info("join network done")
   337  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
   338  }
   339  
   340  func (nDB *NetworkDB) dbLeaveNetwork(w http.ResponseWriter, r *http.Request) {
   341  	_ = r.ParseForm()
   342  	diagnostic.DebugHTTPForm(r)
   343  	_, json := diagnostic.ParseHTTPFormOptions(r)
   344  
   345  	// audit logs
   346  	logger := log.G(context.TODO()).WithFields(log.Fields{
   347  		"component": "diagnostic",
   348  		"remoteIP":  r.RemoteAddr,
   349  		"method":    caller.Name(0),
   350  		"url":       r.URL.String(),
   351  	})
   352  	logger.Info("leave network")
   353  
   354  	if len(r.Form["nid"]) < 1 {
   355  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
   356  		logger.Error("leave network failed, wrong input")
   357  		diagnostic.HTTPReply(w, rsp, json)
   358  		return
   359  	}
   360  
   361  	nid := r.Form["nid"][0]
   362  
   363  	if err := nDB.LeaveNetwork(nid); err != nil {
   364  		logger.WithError(err).Error("leave network failed")
   365  		diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
   366  		return
   367  	}
   368  	logger.Info("leave network done")
   369  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
   370  }
   371  
   372  func (nDB *NetworkDB) dbGetTable(w http.ResponseWriter, r *http.Request) {
   373  	_ = r.ParseForm()
   374  	diagnostic.DebugHTTPForm(r)
   375  	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
   376  
   377  	// audit logs
   378  	logger := log.G(context.TODO()).WithFields(log.Fields{
   379  		"component": "diagnostic",
   380  		"remoteIP":  r.RemoteAddr,
   381  		"method":    caller.Name(0),
   382  		"url":       r.URL.String(),
   383  	})
   384  	logger.Info("get table")
   385  
   386  	if len(r.Form["tname"]) < 1 ||
   387  		len(r.Form["nid"]) < 1 {
   388  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id", r.URL.Path))
   389  		logger.Error("get table failed, wrong input")
   390  		diagnostic.HTTPReply(w, rsp, json)
   391  		return
   392  	}
   393  
   394  	tname := r.Form["tname"][0]
   395  	nid := r.Form["nid"][0]
   396  
   397  	table := nDB.GetTableByNetwork(tname, nid)
   398  	rsp := &diagnostic.TableObj{Length: len(table)}
   399  	i := 0
   400  	for k, v := range table {
   401  		var encodedValue string
   402  		if unsafe {
   403  			encodedValue = string(v.Value)
   404  		} else {
   405  			encodedValue = base64.StdEncoding.EncodeToString(v.Value)
   406  		}
   407  		rsp.Elements = append(rsp.Elements,
   408  			&diagnostic.TableEntryObj{
   409  				Index: i,
   410  				Key:   k,
   411  				Value: encodedValue,
   412  				Owner: v.owner,
   413  			})
   414  		i++
   415  	}
   416  	logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done")
   417  	diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
   418  }
   419  
   420  func (nDB *NetworkDB) dbNetworkStats(w http.ResponseWriter, r *http.Request) {
   421  	_ = r.ParseForm()
   422  	diagnostic.DebugHTTPForm(r)
   423  	_, json := diagnostic.ParseHTTPFormOptions(r)
   424  
   425  	// audit logs
   426  	logger := log.G(context.TODO()).WithFields(log.Fields{
   427  		"component": "diagnostic",
   428  		"remoteIP":  r.RemoteAddr,
   429  		"method":    caller.Name(0),
   430  		"url":       r.URL.String(),
   431  	})
   432  	logger.Info("network stats")
   433  
   434  	if len(r.Form["nid"]) < 1 {
   435  		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path))
   436  		logger.Error("network stats failed, wrong input")
   437  		diagnostic.HTTPReply(w, rsp, json)
   438  		return
   439  	}
   440  
   441  	nDB.RLock()
   442  	networks := nDB.networks[nDB.config.NodeID]
   443  	network, ok := networks[r.Form["nid"][0]]
   444  
   445  	entries := -1
   446  	qLen := -1
   447  	if ok {
   448  		entries = int(network.entriesNumber.Load())
   449  		qLen = network.tableBroadcasts.NumQueued()
   450  	}
   451  	nDB.RUnlock()
   452  
   453  	rsp := diagnostic.CommandSucceed(&diagnostic.NetworkStatsResult{Entries: entries, QueueLen: qLen})
   454  	logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network stats done")
   455  	diagnostic.HTTPReply(w, rsp, json)
   456  }