mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-06 17:29:15 +08:00
Mid way through adopting rqlite
This commit is contained in:
@@ -1,25 +1,23 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"io"
|
||||
"math/rand"
|
||||
|
||||
// "fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gravitl/netmaker/database"
|
||||
"github.com/gravitl/netmaker/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/mongoconn"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
func extClientHandlers(r *mux.Router) {
|
||||
@@ -98,34 +96,22 @@ func getNetworkExtClients(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func GetNetworkExtClients(network string) ([]models.ExtClient, error) {
|
||||
var extclients []models.ExtClient
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
filter := bson.M{"network": network}
|
||||
//Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
||||
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||
|
||||
records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
|
||||
if err != nil {
|
||||
return []models.ExtClient{}, err
|
||||
return extclients, err
|
||||
}
|
||||
defer cancel()
|
||||
for cur.Next(context.TODO()) {
|
||||
//Using a different model for the ReturnExtClient (other than regular extclient).
|
||||
//Either we should do this for ALL structs (so Networks and Keys)
|
||||
//OR we should just use the original struct
|
||||
//My preference is to make some new return structs
|
||||
//TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
|
||||
for _, value := range records {
|
||||
var extclient models.ExtClient
|
||||
err := cur.Decode(&extclient)
|
||||
err = json.Unmarshal([]byte(value), &extclient)
|
||||
if err != nil {
|
||||
return []models.ExtClient{}, err
|
||||
continue
|
||||
}
|
||||
if extclient.Network == network {
|
||||
extclients = append(extclients, extclient)
|
||||
}
|
||||
// add item our array of extclients
|
||||
extclients = append(extclients, extclient)
|
||||
}
|
||||
//TODO: Another fatal error we should take care of.
|
||||
if err := cur.Err(); err != nil {
|
||||
return []models.ExtClient{}, err
|
||||
}
|
||||
return extclients, nil
|
||||
return extclients, err
|
||||
}
|
||||
|
||||
//A separate function to get all extclients, not just extclients for a particular network.
|
||||
@@ -149,58 +135,60 @@ func getExtClient(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
var extclient models.ExtClient
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&extclient)
|
||||
clientid := params["clientid"]
|
||||
network := params["network"]
|
||||
client, err := GetExtClient(clientid, network)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
defer cancel()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(extclient)
|
||||
json.NewEncoder(w).Encode(client)
|
||||
}
|
||||
|
||||
func GetExtClient(clientid string, network string) (models.ExtClient, error) {
|
||||
var extclient models.ExtClient
|
||||
key, err := functions.GetRecordKey(clientid, network)
|
||||
if err != nil {
|
||||
return extclient, err
|
||||
}
|
||||
data, err := database.FetchRecord(database.EXT_CLIENT_TABLE_NAME, key)
|
||||
if err != nil {
|
||||
return extclient, err
|
||||
}
|
||||
err = json.Unmarshal([]byte(data), &extclient)
|
||||
|
||||
return extclient, err
|
||||
}
|
||||
|
||||
//Get an individual extclient. Nothin fancy here folks.
|
||||
func getExtClientConf(w http.ResponseWriter, r *http.Request) {
|
||||
// set header.
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
// set header.
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
||||
var extclient models.ExtClient
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&extclient)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
gwnode, err := functions.GetNodeByMacAddress(extclient.Network, extclient.IngressGatewayID)
|
||||
if err != nil {
|
||||
fmt.Println("Could not retrieve Ingress Gateway Node " + extclient.IngressGatewayID)
|
||||
var params = mux.Vars(r)
|
||||
clientid := params["clientid"]
|
||||
networkid := params["network"]
|
||||
client, err := GetExtClient(clientid, networkid)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
network, err := functions.GetParentNetwork(extclient.Network)
|
||||
if err != nil {
|
||||
fmt.Println("Could not retrieve Ingress Gateway Network " + extclient.Network)
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
gwnode, err := functions.GetNodeByMacAddress(client.Network, client.IngressGatewayID)
|
||||
if err != nil {
|
||||
fmt.Println("Could not retrieve Ingress Gateway Node " + client.IngressGatewayID)
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
network, err := functions.GetParentNetwork(client.Network)
|
||||
if err != nil {
|
||||
fmt.Println("Could not retrieve Ingress Gateway Network " + client.Network)
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
keepalive := ""
|
||||
if network.DefaultKeepalive != 0 {
|
||||
keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive))
|
||||
@@ -216,12 +204,12 @@ AllowedIPs = %s
|
||||
Endpoint = %s
|
||||
%s
|
||||
|
||||
`, extclient.Address + "/32",
|
||||
extclient.PrivateKey,
|
||||
gwnode.PublicKey,
|
||||
network.AddressRange,
|
||||
gwendpoint,
|
||||
keepalive)
|
||||
`, client.Address+"/32",
|
||||
client.PrivateKey,
|
||||
gwnode.PublicKey,
|
||||
network.AddressRange,
|
||||
gwendpoint,
|
||||
keepalive)
|
||||
|
||||
if params["type"] == "qr" {
|
||||
bytes, err := qrcode.Encode(config, qrcode.Medium, 220)
|
||||
@@ -240,21 +228,19 @@ Endpoint = %s
|
||||
}
|
||||
|
||||
if params["type"] == "file" {
|
||||
name := extclient.ClientID + ".conf"
|
||||
w.Header().Set("Content-Type", "application/config")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=\"" + name + "\"")
|
||||
name := client.ClientID + ".conf"
|
||||
w.Header().Set("Content-Type", "application/config")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := fmt.Fprint(w, config)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
defer cancel()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(extclient)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(client)
|
||||
}
|
||||
|
||||
func CreateExtClient(extclient models.ExtClient) error {
|
||||
@@ -276,25 +262,26 @@ func CreateExtClient(extclient models.ExtClient) error {
|
||||
extclient.Address = newAddress
|
||||
}
|
||||
|
||||
if extclient.ClientID == "" {
|
||||
clientid := StringWithCharset(7, charset)
|
||||
clientname := "client-" + clientid
|
||||
extclient.ClientID = clientname
|
||||
}
|
||||
if extclient.ClientID == "" {
|
||||
clientid := StringWithCharset(7, charset)
|
||||
clientname := "client-" + clientid
|
||||
extclient.ClientID = clientname
|
||||
}
|
||||
|
||||
extclient.LastModified = time.Now().Unix()
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
// insert our network into the network table
|
||||
_, err := collection.InsertOne(ctx, extclient)
|
||||
defer cancel()
|
||||
key, err := functions.GetRecordKey(extclient.ClientID, extclient.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := json.Marshal(&extclient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
||||
return err
|
||||
}
|
||||
err = SetNetworkNodesLastModified(extclient.Network)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -322,9 +309,9 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
|
||||
extclient.IngressGatewayID = macaddress
|
||||
node, err := functions.GetNodeByMacAddress(networkName, macaddress)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
extclient.IngressGatewayEndpoint = node.Endpoint + ":" + strconv.FormatInt(int64(node.ListenPort), 10)
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&extclient)
|
||||
@@ -361,71 +348,49 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
||||
// returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||
// return
|
||||
// }
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&oldExtClient)
|
||||
key, err := functions.GetRecordKey(params["clientid"], params["network"])
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
data, err := database.FetchRecord(database.EXT_CLIENT_TABLE_NAME, key)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal([]byte(data), &oldExtClient); err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
newclient, err := UpdateExtClient(newExtClient.ClientID, params["network"], oldExtClient)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
functions.PrintUserLog(r.Header.Get("user"), "updated client "+newExtClient.ClientID, 1)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(newclient)
|
||||
}
|
||||
|
||||
func UpdateExtClient(newclientid string, network string, client models.ExtClient) (models.ExtClient, error) {
|
||||
|
||||
//collection := mongoconn.ConnectDB()
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
// Create filter
|
||||
filter := bson.M{"clientid": client.ClientID, "network": network}
|
||||
|
||||
// prepare update model.
|
||||
update := bson.D{
|
||||
{"$set", bson.D{
|
||||
{"clientid", newclientid},
|
||||
}},
|
||||
}
|
||||
var clientupdate models.ExtClient
|
||||
|
||||
err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&clientupdate)
|
||||
|
||||
defer cancel()
|
||||
|
||||
return clientupdate, err
|
||||
err := DeleteExtClient(network, client.ClientID)
|
||||
if err != nil {
|
||||
return client, err
|
||||
}
|
||||
client.ClientID = newclientid
|
||||
CreateExtClient(client)
|
||||
return client, err
|
||||
}
|
||||
|
||||
func DeleteExtClient(network string, clientid string) (bool, error) {
|
||||
|
||||
deleted := false
|
||||
|
||||
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||
|
||||
filter := bson.M{"network": network, "clientid": clientid}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
result, err := collection.DeleteOne(ctx, filter)
|
||||
|
||||
deletecount := result.DeletedCount
|
||||
|
||||
if deletecount > 0 {
|
||||
deleted = true
|
||||
func DeleteExtClient(network string, clientid string) error {
|
||||
key, err := functions.GetRecordKey(clientid, network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer cancel()
|
||||
|
||||
fmt.Println("Deleted extclient client " + clientid + " from network " + network)
|
||||
return deleted, err
|
||||
err = database.DeleteRecord(database.EXT_CLIENT_TABLE_NAME, key)
|
||||
return err
|
||||
}
|
||||
|
||||
//Delete a extclient
|
||||
@@ -437,28 +402,27 @@ func deleteExtClient(w http.ResponseWriter, r *http.Request) {
|
||||
// get params
|
||||
var params = mux.Vars(r)
|
||||
|
||||
success, err := DeleteExtClient(params["network"], params["clientid"])
|
||||
err := DeleteExtClient(params["network"], params["clientid"])
|
||||
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
} else if !success {
|
||||
err = errors.New("Could not delete extclient " + params["clientid"])
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
functions.PrintUserLog(r.Header.Get("user"),
|
||||
"Deleted extclient client "+params["clientid"]+" from network "+params["network"], 1)
|
||||
returnSuccessResponse(w, r, params["clientid"]+" deleted.")
|
||||
}
|
||||
|
||||
func StringWithCharset(length int, charset string) string {
|
||||
b := make([]byte, length)
|
||||
for i := range b {
|
||||
b[i] = charset[seededRand.Intn(len(charset))]
|
||||
}
|
||||
return string(b)
|
||||
b := make([]byte, length)
|
||||
for i := range b {
|
||||
b[i] = charset[seededRand.Intn(len(charset))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
var seededRand *rand.Rand = rand.New(
|
||||
rand.NewSource(time.Now().UnixNano()))
|
||||
rand.NewSource(time.Now().UnixNano()))
|
||||
|
Reference in New Issue
Block a user