Skip to content

Commit 8b876c1

Browse files
authored
Merge pull request #3624 from gravitl/release-v1.0.0
Release v1.0.0
2 parents fa4fb3a + c3935d1 commit 8b876c1

File tree

22 files changed

+1119
-164
lines changed

22 files changed

+1119
-164
lines changed

controllers/dns.go

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package controller
22

33
import (
4+
"context"
45
"encoding/json"
56
"errors"
67
"fmt"
78
"net/http"
89
"strings"
10+
"time"
911

12+
"github.com/google/uuid"
1013
"github.com/gorilla/mux"
1114
"github.com/gravitl/netmaker/database"
15+
"github.com/gravitl/netmaker/db"
1216
"github.com/gravitl/netmaker/logger"
1317
"github.com/gravitl/netmaker/logic"
1418
"github.com/gravitl/netmaker/models"
1519
"github.com/gravitl/netmaker/mq"
20+
"github.com/gravitl/netmaker/schema"
1621
"github.com/gravitl/netmaker/servercfg"
22+
"gorm.io/datatypes"
1723
)
1824

1925
func dnsHandlers(r *mux.Router) {
@@ -34,6 +40,274 @@ func dnsHandlers(r *mux.Router) {
3440
Methods(http.MethodPost)
3541
r.HandleFunc("/api/dns/{network}/{domain}", logic.SecurityCheck(true, http.HandlerFunc(deleteDNS))).
3642
Methods(http.MethodDelete)
43+
r.HandleFunc("/api/v1/nameserver", logic.SecurityCheck(true, http.HandlerFunc(createNs))).Methods(http.MethodPost)
44+
r.HandleFunc("/api/v1/nameserver", logic.SecurityCheck(true, http.HandlerFunc(listNs))).Methods(http.MethodGet)
45+
r.HandleFunc("/api/v1/nameserver", logic.SecurityCheck(true, http.HandlerFunc(updateNs))).Methods(http.MethodPut)
46+
r.HandleFunc("/api/v1/nameserver", logic.SecurityCheck(true, http.HandlerFunc(deleteNs))).Methods(http.MethodDelete)
47+
r.HandleFunc("/api/v1/nameserver/global", logic.SecurityCheck(true, http.HandlerFunc(getGlobalNs))).Methods(http.MethodGet)
48+
}
49+
50+
// @Summary List Global Nameservers
51+
// @Router /api/v1/nameserver/global [get]
52+
// @Tags Auth
53+
// @Accept json
54+
// @Param query network string
55+
// @Success 200 {object} models.SuccessResponse
56+
// @Failure 400 {object} models.ErrorResponse
57+
// @Failure 401 {object} models.ErrorResponse
58+
// @Failure 500 {object} models.ErrorResponse
59+
func getGlobalNs(w http.ResponseWriter, r *http.Request) {
60+
61+
logic.ReturnSuccessResponseWithJson(w, r, logic.GlobalNsList, "fetched nameservers")
62+
}
63+
64+
// @Summary Create Nameserver
65+
// @Router /api/v1/nameserver [post]
66+
// @Tags DNS
67+
// @Accept json
68+
// @Param body body models.NameserverReq
69+
// @Success 200 {object} models.SuccessResponse
70+
// @Failure 400 {object} models.ErrorResponse
71+
// @Failure 401 {object} models.ErrorResponse
72+
// @Failure 500 {object} models.ErrorResponse
73+
func createNs(w http.ResponseWriter, r *http.Request) {
74+
75+
var req schema.Nameserver
76+
err := json.NewDecoder(r.Body).Decode(&req)
77+
if err != nil {
78+
logger.Log(0, "error decoding request body: ",
79+
err.Error())
80+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
81+
return
82+
}
83+
if err := logic.ValidateNameserverReq(req); err != nil {
84+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
85+
return
86+
}
87+
if req.Tags == nil {
88+
req.Tags = make(datatypes.JSONMap)
89+
}
90+
if gNs, ok := logic.GlobalNsList[req.Name]; ok {
91+
req.Servers = gNs.IPs
92+
}
93+
if !servercfg.IsPro {
94+
req.Tags = datatypes.JSONMap{
95+
"*": struct{}{},
96+
}
97+
}
98+
if req.MatchAll {
99+
req.MatchDomains = []string{"."}
100+
}
101+
ns := schema.Nameserver{
102+
ID: uuid.New().String(),
103+
Name: req.Name,
104+
NetworkID: req.NetworkID,
105+
Description: req.Description,
106+
MatchAll: req.MatchAll,
107+
MatchDomains: req.MatchDomains,
108+
Servers: req.Servers,
109+
Tags: req.Tags,
110+
Status: true,
111+
CreatedBy: r.Header.Get("user"),
112+
CreatedAt: time.Now().UTC(),
113+
}
114+
115+
err = ns.Create(db.WithContext(r.Context()))
116+
if err != nil {
117+
logic.ReturnErrorResponse(
118+
w,
119+
r,
120+
logic.FormatError(errors.New("error creating nameserver "+err.Error()), logic.Internal),
121+
)
122+
return
123+
}
124+
logic.LogEvent(&models.Event{
125+
Action: models.Create,
126+
Source: models.Subject{
127+
ID: r.Header.Get("user"),
128+
Name: r.Header.Get("user"),
129+
Type: models.UserSub,
130+
},
131+
TriggeredBy: r.Header.Get("user"),
132+
Target: models.Subject{
133+
ID: ns.ID,
134+
Name: ns.Name,
135+
Type: models.NameserverSub,
136+
},
137+
NetworkID: models.NetworkID(ns.NetworkID),
138+
Origin: models.Dashboard,
139+
})
140+
141+
go mq.PublishPeerUpdate(false)
142+
logic.ReturnSuccessResponseWithJson(w, r, ns, "created nameserver")
143+
}
144+
145+
// @Summary List Nameservers
146+
// @Router /api/v1/nameserver [get]
147+
// @Tags Auth
148+
// @Accept json
149+
// @Param query network string
150+
// @Success 200 {object} models.SuccessResponse
151+
// @Failure 400 {object} models.ErrorResponse
152+
// @Failure 401 {object} models.ErrorResponse
153+
// @Failure 500 {object} models.ErrorResponse
154+
func listNs(w http.ResponseWriter, r *http.Request) {
155+
156+
network := r.URL.Query().Get("network")
157+
if network == "" {
158+
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("network is required"), "badrequest"))
159+
return
160+
}
161+
ns := schema.Nameserver{NetworkID: network}
162+
list, err := ns.ListByNetwork(db.WithContext(r.Context()))
163+
if err != nil {
164+
logic.ReturnErrorResponse(
165+
w,
166+
r,
167+
logic.FormatError(errors.New("error listing nameservers "+err.Error()), "internal"),
168+
)
169+
return
170+
}
171+
logic.ReturnSuccessResponseWithJson(w, r, list, "fetched nameservers")
172+
}
173+
174+
// @Summary Update Nameserver
175+
// @Router /api/v1/nameserver [put]
176+
// @Tags Auth
177+
// @Accept json
178+
// @Param body body models.NameserverReq
179+
// @Success 200 {object} models.SuccessResponse
180+
// @Failure 400 {object} models.ErrorResponse
181+
// @Failure 401 {object} models.ErrorResponse
182+
// @Failure 500 {object} models.ErrorResponse
183+
func updateNs(w http.ResponseWriter, r *http.Request) {
184+
185+
var updateNs schema.Nameserver
186+
err := json.NewDecoder(r.Body).Decode(&updateNs)
187+
if err != nil {
188+
logger.Log(0, "error decoding request body: ",
189+
err.Error())
190+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
191+
return
192+
}
193+
194+
if err := logic.ValidateNameserverReq(updateNs); err != nil {
195+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
196+
return
197+
}
198+
if updateNs.Tags == nil {
199+
updateNs.Tags = make(datatypes.JSONMap)
200+
}
201+
202+
ns := schema.Nameserver{ID: updateNs.ID}
203+
err = ns.Get(db.WithContext(r.Context()))
204+
if err != nil {
205+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
206+
return
207+
}
208+
var updateStatus bool
209+
var updateMatchAll bool
210+
if updateNs.Status != ns.Status {
211+
updateStatus = true
212+
}
213+
if updateNs.MatchAll != ns.MatchAll {
214+
updateMatchAll = true
215+
}
216+
event := &models.Event{
217+
Action: models.Update,
218+
Source: models.Subject{
219+
ID: r.Header.Get("user"),
220+
Name: r.Header.Get("user"),
221+
Type: models.UserSub,
222+
},
223+
TriggeredBy: r.Header.Get("user"),
224+
Target: models.Subject{
225+
ID: ns.ID,
226+
Name: updateNs.Name,
227+
Type: models.NameserverSub,
228+
},
229+
Diff: models.Diff{
230+
Old: ns,
231+
New: updateNs,
232+
},
233+
NetworkID: models.NetworkID(ns.NetworkID),
234+
Origin: models.Dashboard,
235+
}
236+
ns.Servers = updateNs.Servers
237+
ns.Tags = updateNs.Tags
238+
ns.MatchDomains = updateNs.MatchDomains
239+
ns.MatchAll = updateNs.MatchAll
240+
ns.Description = updateNs.Description
241+
ns.Name = updateNs.Name
242+
ns.Status = updateNs.Status
243+
ns.UpdatedAt = time.Now().UTC()
244+
245+
err = ns.Update(db.WithContext(context.TODO()))
246+
if err != nil {
247+
logic.ReturnErrorResponse(
248+
w,
249+
r,
250+
logic.FormatError(errors.New("error creating egress resource"+err.Error()), "internal"),
251+
)
252+
return
253+
}
254+
if updateStatus {
255+
ns.UpdateStatus(db.WithContext(context.TODO()))
256+
}
257+
if updateMatchAll {
258+
ns.UpdateMatchAll(db.WithContext(context.TODO()))
259+
}
260+
logic.LogEvent(event)
261+
go mq.PublishPeerUpdate(false)
262+
logic.ReturnSuccessResponseWithJson(w, r, ns, "updated nameserver")
263+
}
264+
265+
// @Summary Delete Nameserver Resource
266+
// @Router /api/v1/nameserver [delete]
267+
// @Tags Auth
268+
// @Accept json
269+
// @Param body body models.Egress
270+
// @Success 200 {object} models.SuccessResponse
271+
// @Failure 400 {object} models.ErrorResponse
272+
// @Failure 401 {object} models.ErrorResponse
273+
// @Failure 500 {object} models.ErrorResponse
274+
func deleteNs(w http.ResponseWriter, r *http.Request) {
275+
276+
id := r.URL.Query().Get("id")
277+
if id == "" {
278+
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("id is required"), "badrequest"))
279+
return
280+
}
281+
ns := schema.Nameserver{ID: id}
282+
err := ns.Get(db.WithContext(r.Context()))
283+
if err != nil {
284+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.BadReq))
285+
return
286+
}
287+
err = ns.Delete(db.WithContext(r.Context()))
288+
if err != nil {
289+
logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.Internal))
290+
return
291+
}
292+
logic.LogEvent(&models.Event{
293+
Action: models.Delete,
294+
Source: models.Subject{
295+
ID: r.Header.Get("user"),
296+
Name: r.Header.Get("user"),
297+
Type: models.UserSub,
298+
},
299+
TriggeredBy: r.Header.Get("user"),
300+
Target: models.Subject{
301+
ID: ns.ID,
302+
Name: ns.Name,
303+
Type: models.NameserverSub,
304+
},
305+
NetworkID: models.NetworkID(ns.NetworkID),
306+
Origin: models.Dashboard,
307+
})
308+
309+
go mq.PublishPeerUpdate(false)
310+
logic.ReturnSuccessResponseWithJson(w, r, nil, "deleted nameserver resource")
37311
}
38312

39313
// @Summary Gets node DNS entries associated with a network

0 commit comments

Comments
 (0)