-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.go
149 lines (130 loc) · 4.68 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"fmt"
"github.com/aarnaud/ipxeblue/controllers"
_ "github.com/aarnaud/ipxeblue/docs"
"github.com/aarnaud/ipxeblue/midlewares"
"github.com/aarnaud/ipxeblue/utils"
"github.com/gin-contrib/cors"
"github.com/gin-contrib/logger"
"github.com/gin-gonic/gin"
"github.com/pin/tftp/v3"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"net/http"
"os"
"time"
)
// @title ipxeblue API
// @version 0.1
// @description Manage PXE boot
// @termsOfService http://swagger.io/terms/
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
func main() {
zerolog.SetGlobalLevel(zerolog.InfoLevel)
appconf := utils.GetConfig()
router := gin.New()
router.Use(logger.SetLogger(logger.Config{
SkipPath: []string{"/healthz"},
}))
router.Use(gin.Recovery())
// CORS for https://foo.com and https://github.com origins, allowing:
// - PUT and PATCH methods
// - Origin header
// - Credentials share
// - Preflight requests cached for 12 hours
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"http://localhost:3000", "http://localhost:8080"},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"},
AllowHeaders: []string{"Origin", "Content-Type"},
ExposeHeaders: []string{"x-total-count", "content-length"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
router.LoadHTMLGlob("templates/*")
db := utils.Database()
filestore := utils.NewFileStore(appconf)
log.Info().Msg("starting TokenCleaner in goroutine")
go utils.TokenCleaner(db)
// Provide db variable to controllers
router.Use(func(c *gin.Context) {
c.Set("db", db)
c.Set("filestore", filestore)
c.Set("config", appconf)
c.Header("Cache-Control", "no-store, max-age=0")
c.Next()
})
if gin.Mode() == gin.DebugMode {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
// Configure SwaggerUI
url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") // The url pointing to API definition
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
// proxies UI call to nodejs react server
router.Use(midlewares.MidlewareDevWebUI())
} else {
// Serve react-admin webui
router.Static("/admin", "./admin")
}
router.GET("/healthz", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
})
if appconf.GrubSupportEnabled {
// Grub request without auth
log.Info().Msg("enabling grub http endpoint")
router.GET("/grub/", controllers.GrubScript)
}
// grub don't support long http queries
// using TFTP to pass positional metadata in tftp path
if appconf.TFTPEnabled {
s := tftp.NewServer(controllers.GetTFTPReader(appconf, db), controllers.GetTFTPWriter(appconf))
s.SetTimeout(30 * time.Second)
go func() {
log.Info().Msg("starting tftp server")
err := s.ListenAndServe(":69")
if err != nil {
fmt.Fprintf(os.Stdout, "server: %v\n", err)
}
}()
}
// iPXE request with auth
ipxeroute := router.Group("/", midlewares.BasicAuthIpxeAccount(false))
ipxeroute.GET("/", controllers.IpxeScript)
router.HEAD("/files/public/:uuid/*filepath", controllers.DownloadPublicFile)
router.GET("/files/public/:uuid/*filepath", controllers.DownloadPublicFile)
router.HEAD("/files/token/:token/:uuid/*filepath", controllers.DownloadProtectedFile)
router.GET("/files/token/:token/:uuid/*filepath", controllers.DownloadProtectedFile)
var v1 *gin.RouterGroup
if appconf.EnableAPIAuth {
// API
v1 = router.Group("/api/v1", midlewares.BasicAuthIpxeAccount(true))
} else {
// API
v1 = router.Group("/api/v1")
}
// Computer
v1.GET("/computers", controllers.ListComputers)
v1.GET("/computers/:id", controllers.GetComputer)
v1.PUT("/computers/:id", controllers.UpdateComputer)
v1.DELETE("/computers/:id", controllers.DeleteComputer)
// IPXE account
v1.GET("/ipxeaccounts", controllers.ListIpxeaccount)
v1.GET("/ipxeaccounts/:username", controllers.GetIpxeaccount)
v1.POST("/ipxeaccounts", controllers.CreateIpxeaccount)
v1.PUT("/ipxeaccounts/:username", controllers.UpdateIpxeaccount)
v1.DELETE("/ipxeaccounts/:username", controllers.DeleteIpxeaccount)
// Bootentry
v1.GET("/bootentries", controllers.ListBootentries)
v1.GET("/bootentries/:uuid", controllers.GetBootentry)
v1.POST("/bootentries", controllers.CreateBootentry)
v1.PUT("/bootentries/:uuid", controllers.UpdateBootentry)
v1.DELETE("/bootentries/:uuid", controllers.DeleteBootentry)
v1.POST("/bootentries/:uuid/files/:name", controllers.UploadBootentryFile)
v1.GET("/bootentries/:uuid/files/:name", controllers.DownloadBootentryFile)
log.Info().Msg("starting http server")
router.Run(fmt.Sprintf(":%d", appconf.Port))
}