docker.go 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. package v1
  2. import (
  3. "bytes"
  4. json2 "encoding/json"
  5. "github.com/IceWhaleTech/CasaOS/model"
  6. "github.com/IceWhaleTech/CasaOS/pkg/docker"
  7. upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
  8. "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
  9. ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
  10. oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
  11. port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
  12. "github.com/IceWhaleTech/CasaOS/pkg/utils/random"
  13. "github.com/IceWhaleTech/CasaOS/service"
  14. "github.com/IceWhaleTech/CasaOS/service/docker_base"
  15. model2 "github.com/IceWhaleTech/CasaOS/service/model"
  16. "github.com/IceWhaleTech/CasaOS/types"
  17. "github.com/gin-gonic/gin"
  18. "github.com/gorilla/websocket"
  19. "github.com/jinzhu/copier"
  20. uuid "github.com/satori/go.uuid"
  21. "net/http"
  22. "reflect"
  23. "strconv"
  24. "strings"
  25. "time"
  26. )
  27. var upgrader = websocket.Upgrader{
  28. ReadBufferSize: 1024,
  29. WriteBufferSize: 1024,
  30. CheckOrigin: func(r *http.Request) bool { return true },
  31. HandshakeTimeout: time.Duration(time.Second * 5),
  32. }
  33. //打开docker的terminal
  34. func DockerTerminal(c *gin.Context) {
  35. col := c.DefaultQuery("cols", "100")
  36. row := c.DefaultQuery("rows", "30")
  37. conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
  38. if err != nil {
  39. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
  40. return
  41. }
  42. defer conn.Close()
  43. container := c.Param("id")
  44. hr, err := service.Exec(container, row, col)
  45. if err != nil {
  46. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
  47. return
  48. }
  49. // 关闭I/O流
  50. defer hr.Close()
  51. // 退出进程
  52. defer func() {
  53. hr.Conn.Write([]byte("exit\r"))
  54. }()
  55. go func() {
  56. docker.WsWriterCopy(hr.Conn, conn)
  57. }()
  58. docker.WsReaderCopy(conn, hr.Conn)
  59. }
  60. //打开本机的ssh接口
  61. func WsSsh(c *gin.Context) {
  62. wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
  63. defer wsConn.Close()
  64. cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
  65. rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
  66. client, _ := docker.NewSshClient()
  67. defer client.Close()
  68. ssConn, _ := docker.NewSshConn(cols, rows, client)
  69. defer ssConn.Close()
  70. quitChan := make(chan bool, 3)
  71. var logBuff = new(bytes.Buffer)
  72. go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
  73. go ssConn.SendComboOutput(wsConn, quitChan)
  74. go ssConn.SessionWait(quitChan)
  75. <-quitChan
  76. }
  77. //安装进度推送
  78. func SpeedPush(c *gin.Context) {
  79. //token := c.Query("token")
  80. //if len(token) == 0 || token != config.UserInfo.Token {
  81. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_AUTH_TOKEN, Message: oasis_err2.GetMsg(oasis_err2.ERROR_AUTH_TOKEN)})
  82. // return
  83. //}
  84. //ws, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
  85. //defer ws.Close()
  86. //
  87. //for {
  88. // select {
  89. // case msg := <-WSMSG:
  90. // ws.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintln(msg)))
  91. // }
  92. //}
  93. }
  94. // @Summary 安装app(该接口需要post json数据)
  95. // @Produce application/json
  96. // @Accept application/json
  97. // @Tags app
  98. // @Param id path int true "id"
  99. // @Param port formData int true "主端口"
  100. // @Param tcp formData string false "tcp端口"
  101. // @Param udp formData string false "udp端口"
  102. // @Param env formData string false "环境变量"
  103. // @Security ApiKeyAuth
  104. // @Success 200 {string} string "ok"
  105. // @Router /app/install/{id} [post]
  106. func InstallApp(c *gin.Context) {
  107. appId := c.Param("id")
  108. var appInfo model.ServerAppList
  109. m := model.CustomizationPostData{}
  110. c.BindJSON(&m)
  111. const CUSTOM = "custom"
  112. var dockerImage string
  113. var dockerImageVersion string
  114. //检查端口
  115. if len(m.PortMap) > 0 && m.PortMap != "0" {
  116. //c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
  117. portMap, _ := strconv.Atoi(m.PortMap)
  118. if !port2.IsPortAvailable(portMap, "tcp") {
  119. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap})
  120. return
  121. }
  122. }
  123. //if len(m.Port) == 0 || m.Port == "0" {
  124. // m.Port = m.PortMap
  125. //}
  126. imageArr := strings.Split(m.Image, ":")
  127. if len(imageArr) == 2 {
  128. dockerImage = imageArr[0]
  129. dockerImageVersion = imageArr[1]
  130. } else {
  131. dockerImage = m.Image
  132. dockerImageVersion = "latest"
  133. }
  134. if m.Origin != "custom" {
  135. appInfo = service.MyService.App().GetServerAppInfo(appId)
  136. } else {
  137. appInfo.Title = m.Label
  138. appInfo.Description = m.Description
  139. appInfo.Icon = m.Icon
  140. appInfo.ScreenshotLink = model.Strings{}
  141. appInfo.NetworkModel = m.NetworkModel
  142. appInfo.Tags = model.Strings{}
  143. appInfo.Tagline = ""
  144. appInfo.Index = m.Index
  145. }
  146. for _, u := range m.Ports {
  147. if u.Protocol == "udp" {
  148. t, _ := strconv.Atoi(u.CommendPort)
  149. if !port2.IsPortAvailable(t, "udp") {
  150. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  151. return
  152. }
  153. } else if u.Protocol == "tcp" {
  154. te, _ := strconv.Atoi(u.CommendPort)
  155. if !port2.IsPortAvailable(te, "tcp") {
  156. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  157. return
  158. }
  159. } else if u.Protocol == "both" {
  160. t, _ := strconv.Atoi(u.CommendPort)
  161. if !port2.IsPortAvailable(t, "udp") {
  162. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  163. return
  164. }
  165. te, _ := strconv.Atoi(u.CommendPort)
  166. if !port2.IsPortAvailable(te, "tcp") {
  167. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  168. return
  169. }
  170. }
  171. }
  172. for _, device := range m.Devices {
  173. if file.CheckNotExist(device.Path) {
  174. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)})
  175. return
  176. }
  177. }
  178. //restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
  179. //if len(restart) > 0 {
  180. //
  181. //}
  182. //
  183. //privileged := c.PostForm("privileged") //是否处于特权模式
  184. //if len(privileged) > 0 {
  185. //
  186. //}
  187. id := uuid.NewV4().String()
  188. var relyMap = make(map[string]string)
  189. go func() {
  190. installLog := model2.AppNotify{}
  191. installLog.CustomId = id
  192. installLog.State = 0
  193. installLog.Message = "installing rely"
  194. installLog.Speed = 10
  195. installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
  196. installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  197. installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  198. service.MyService.Notify().AddLog(installLog)
  199. if m.Origin != "custom" {
  200. for _, plugin := range appInfo.Plugins {
  201. if plugin == "mysql" {
  202. mid := uuid.NewV4().String()
  203. mc := docker_base.MysqlConfig{}
  204. mc.DataBasePassword = random.RandomString(6, false)
  205. mc.DataBaseDB = appInfo.Title
  206. mc.DataBaseUser = "root"
  207. mc.DataBasePort = "3306"
  208. mysqlContainerId, err := docker_base.MysqlCreate(mc, mid, m.CpuShares, m.Memory)
  209. if len(mysqlContainerId) > 0 && err == nil {
  210. mc.DataBaseHost = mid
  211. m.Envs = docker_base.MysqlFilter(mc, m.Envs)
  212. rely := model2.RelyDBModel{}
  213. rely.Type = types.RELY_TYPE_MYSQL
  214. rely.ContainerId = mysqlContainerId
  215. rely.CustomId = mid
  216. rely.ContainerCustomId = id
  217. var msqlConfig model2.MysqlConfigs
  218. //结构体转换
  219. copier.Copy(&msqlConfig, &mc)
  220. rely.Config = msqlConfig
  221. service.MyService.Rely().Create(rely)
  222. relyMap["mysql"] = mid
  223. } else {
  224. docker_base.MysqlDelete(mysqlContainerId)
  225. installLog.State = 0
  226. installLog.Speed = 30
  227. installLog.Message = err.Error()
  228. service.MyService.Notify().UpdateLog(installLog)
  229. }
  230. }
  231. }
  232. }
  233. installLog.Speed = 50
  234. installLog.Message = "pulling"
  235. service.MyService.Notify().UpdateLog(installLog)
  236. // step:下载镜像
  237. err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
  238. if err != nil {
  239. installLog.State = 0
  240. installLog.Speed = 70
  241. installLog.Message = err.Error()
  242. installLog.Type = types.NOTIFY_TYPE_ERROR
  243. service.MyService.Notify().UpdateLog(installLog)
  244. return
  245. }
  246. for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
  247. time.Sleep(time.Second)
  248. }
  249. //if {
  250. //}
  251. //step:创建容器
  252. containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
  253. installLog.ContainerId = containerId
  254. if err != nil {
  255. //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
  256. installLog.State = 0
  257. installLog.Speed = 80
  258. installLog.Type = types.NOTIFY_TYPE_ERROR
  259. installLog.Message = err.Error()
  260. service.MyService.Notify().UpdateLog(installLog)
  261. return
  262. } else {
  263. //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
  264. installLog.Speed = 80
  265. installLog.Message = "starting"
  266. service.MyService.Notify().UpdateLog(installLog)
  267. }
  268. //step:启动容器
  269. err = service.MyService.Docker().DockerContainerStart(id)
  270. if err != nil {
  271. //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
  272. installLog.State = 0
  273. installLog.Type = types.NOTIFY_TYPE_ERROR
  274. installLog.Speed = 90
  275. installLog.Message = err.Error()
  276. service.MyService.Notify().UpdateLog(installLog)
  277. return
  278. } else {
  279. //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
  280. installLog.Speed = 90
  281. if m.Origin != CUSTOM {
  282. installLog.Message = "setting upnp"
  283. } else {
  284. installLog.Message = "nearing completion"
  285. }
  286. service.MyService.Notify().UpdateLog(installLog)
  287. }
  288. if m.Origin != CUSTOM {
  289. //step:启动upnp
  290. if m.EnableUPNP {
  291. upnp, err := upnp2.Gateway()
  292. if err == nil {
  293. for _, p := range m.Ports {
  294. if p.Protocol == "udp" {
  295. upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  296. upnp.LocalHost = ip_helper2.GetLoclIp()
  297. tComment, _ := strconv.Atoi(p.CommendPort)
  298. upnp.AddPortMapping(tComment, tComment, "UDP")
  299. time.Sleep(time.Millisecond * 200)
  300. } else if p.Protocol == "tcp" {
  301. upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  302. upnp.LocalHost = ip_helper2.GetLoclIp()
  303. tComment, _ := strconv.Atoi(p.CommendPort)
  304. upnp.AddPortMapping(tComment, tComment, "TCP")
  305. time.Sleep(time.Millisecond * 200)
  306. } else if p.Protocol == "both" {
  307. upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  308. upnp.LocalHost = ip_helper2.GetLoclIp()
  309. tComment, _ := strconv.Atoi(p.CommendPort)
  310. upnp.AddPortMapping(tComment, tComment, "UDP")
  311. time.Sleep(time.Millisecond * 200)
  312. upnp.AddPortMapping(tComment, tComment, "TCP")
  313. time.Sleep(time.Millisecond * 200)
  314. }
  315. }
  316. }
  317. if err != nil {
  318. //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
  319. installLog.State = 0
  320. installLog.Speed = 95
  321. installLog.Type = types.NOTIFY_TYPE_ERROR
  322. installLog.Message = err.Error()
  323. service.MyService.Notify().UpdateLog(installLog)
  324. } else {
  325. //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
  326. installLog.Speed = 95
  327. installLog.Message = "checking"
  328. service.MyService.Notify().UpdateLog(installLog)
  329. }
  330. }
  331. }
  332. //step: 启动成功 检查容器状态确认启动成功
  333. container, err := service.MyService.Docker().DockerContainerInfo(id)
  334. if err != nil && container.ContainerJSONBase.State.Running {
  335. //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
  336. installLog.State = 0
  337. installLog.Speed = 100
  338. installLog.Type = types.NOTIFY_TYPE_ERROR
  339. installLog.Message = err.Error()
  340. service.MyService.Notify().UpdateLog(installLog)
  341. return
  342. } else {
  343. //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
  344. installLog.Speed = 100
  345. installLog.Message = "installed"
  346. service.MyService.Notify().UpdateLog(installLog)
  347. }
  348. rely := model.MapStrings{}
  349. copier.Copy(&rely, &relyMap)
  350. portsStr, _ := json2.Marshal(m.Ports)
  351. envsStr, _ := json2.Marshal(m.Envs)
  352. volumesStr, _ := json2.Marshal(m.Volumes)
  353. devicesStr, _ := json2.Marshal(m.Devices)
  354. //step: 保存数据到数据库
  355. md := model2.AppListDBModel{
  356. CustomId: id,
  357. Title: appInfo.Title,
  358. //ScreenshotLink: appInfo.ScreenshotLink,
  359. Slogan: appInfo.Tagline,
  360. Description: appInfo.Description,
  361. //Tags: appInfo.Tags,
  362. Icon: appInfo.Icon,
  363. Version: dockerImageVersion,
  364. ContainerId: containerId,
  365. Image: dockerImage,
  366. Index: appInfo.Index,
  367. //Port: m.Port,
  368. PortMap: m.PortMap,
  369. Label: m.Label,
  370. EnableUPNP: m.EnableUPNP,
  371. Ports: string(portsStr),
  372. Envs: string(envsStr),
  373. Volumes: string(volumesStr),
  374. Position: m.Position,
  375. NetModel: appInfo.NetworkModel,
  376. Restart: m.Restart,
  377. CpuShares: m.CpuShares,
  378. Memory: m.Memory,
  379. Devices: string(devicesStr),
  380. //Rely: rely,
  381. Origin: m.Origin,
  382. CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
  383. UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
  384. }
  385. //if appInfo.NetworkModel == "host" {
  386. // m.PortMap = m.Port
  387. //}
  388. service.MyService.App().SaveContainer(md)
  389. }()
  390. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: id})
  391. }
  392. //// @Summary 自定义安装app(该接口需要post json数据)
  393. //// @Produce application/json
  394. //// @Accept application/json
  395. //// @Tags app
  396. //// @Param id path int true "id"
  397. //// @Param port formData int true "主端口"
  398. //// @Param tcp formData string false "tcp端口"
  399. //// @Param udp formData string false "udp端口"
  400. //// @Param env formData string false "环境变量"
  401. //// @Security ApiKeyAuth
  402. //// @Success 200 {string} string "ok"
  403. //// @Router /app/install/{id} [post]
  404. //func CustomInstallApp(c *gin.Context) {
  405. // //appId := c.Param("id")
  406. // // appInfo := service.MyService.App().GetServerAppInfo(appId)
  407. //
  408. // m := model.CustomizationPostData{}
  409. // c.BindJSON(&m)
  410. // //检查端口
  411. // if len(m.PortMap) == 0 || m.PortMap == "0" {
  412. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
  413. // return
  414. // }
  415. // if len(m.Port) == 0 || m.Port == "0" {
  416. // m.Port = m.PortMap
  417. // }
  418. //
  419. // portMap, _ := strconv.Atoi(m.PortMap)
  420. // if !port2.IsPortAvailable(portMap, "tcp") {
  421. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap})
  422. // return
  423. // }
  424. //
  425. // for _, u := range m.Udp {
  426. // t, _ := strconv.Atoi(u.CommendPort)
  427. // if !port2.IsPortAvailable(t, "udp") {
  428. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  429. // return
  430. // }
  431. // }
  432. //
  433. // for _, t := range m.Tcp {
  434. // te, _ := strconv.Atoi(t.CommendPort)
  435. // if !port2.IsPortAvailable(te, "tcp") {
  436. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + t.CommendPort})
  437. // return
  438. // }
  439. // }
  440. //
  441. // //restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
  442. // //if len(restart) > 0 {
  443. // //
  444. // //}
  445. // //
  446. // //privileged := c.PostForm("privileged") //是否处于特权模式
  447. // //if len(privileged) > 0 {
  448. // //
  449. // //}
  450. //
  451. // err := service.MyService.Docker().DockerPullImage(m.Image)
  452. // if err != nil {
  453. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PULL_IMAGE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PULL_IMAGE_ERROR)})
  454. // }
  455. //
  456. // id := uuid.NewV4().String()
  457. //
  458. // var relyMap = make(map[string]string)
  459. // go func() {
  460. // installLog := model2.AppNotify{}
  461. // installLog.CustomId = id
  462. // installLog.State = 0
  463. // installLog.Message = "installing rely"
  464. // installLog.Speed = 30
  465. // installLog.CreatedAt = time.Now()
  466. // installLog.UpdatedAt = time.Now()
  467. // service.MyService.Notify().AddLog(installLog)
  468. //
  469. // for !service.MyService.Docker().IsExistImage(m.Image) {
  470. // time.Sleep(time.Second)
  471. // }
  472. //
  473. // installLog.Speed = 50
  474. // installLog.Message = "pulling"
  475. // service.MyService.Notify().UpdateLog(installLog)
  476. // // step:下载镜像
  477. //
  478. // var cpd model.PostData
  479. // copier.Copy(&cpd, &m)
  480. // //step:创建容器
  481. // containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, id, cpd, m.NetworkModel, m.Image, "custom")
  482. // installLog.ContainerId = containerId
  483. // if err != nil {
  484. // //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
  485. // installLog.State = 0
  486. // installLog.Speed = 80
  487. // installLog.Message = err.Error()
  488. // service.MyService.Notify().UpdateLog(installLog)
  489. // return
  490. // } else {
  491. // //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
  492. // installLog.Speed = 80
  493. // installLog.Message = "starting"
  494. // service.MyService.Notify().UpdateLog(installLog)
  495. // }
  496. //
  497. // //step:启动容器
  498. // err = service.MyService.Docker().DockerContainerStart(id)
  499. // if err != nil {
  500. // //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
  501. // installLog.State = 0
  502. // installLog.Speed = 90
  503. // installLog.Message = err.Error()
  504. // service.MyService.Notify().UpdateLog(installLog)
  505. // return
  506. // } else {
  507. // //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
  508. // installLog.Speed = 90
  509. // installLog.Message = "setting upnp"
  510. // service.MyService.Notify().UpdateLog(installLog)
  511. // }
  512. //
  513. // //step: 启动成功 检查容器状态确认启动成功
  514. // containerStatus, err := service.MyService.Docker().DockerContainerInfo(id)
  515. // if err != nil && containerStatus.ContainerJSONBase.State.Running {
  516. // //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
  517. // installLog.State = 0
  518. // installLog.Speed = 100
  519. // installLog.Message = err.Error()
  520. // service.MyService.Notify().UpdateLog(installLog)
  521. // return
  522. // } else {
  523. // //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
  524. // installLog.Speed = 100
  525. // installLog.Message = "installed"
  526. // service.MyService.Notify().UpdateLog(installLog)
  527. // }
  528. //
  529. // rely := model.MapStrings{}
  530. //
  531. // copier.Copy(&rely, &relyMap)
  532. //
  533. // //step: 保存数据到数据库
  534. // md := model2.AppListDBModel{
  535. // CustomId: id,
  536. // Title: m.Label,
  537. // // ScreenshotLink: []string,
  538. // Slogan: "",
  539. // Description: m.Description,
  540. // // Tags: ,
  541. // Icon: m.Icon,
  542. // Version: m.Image,
  543. // ContainerId: containerId,
  544. // Image: m.Image,
  545. // Index: "",
  546. // Port: m.Port,
  547. // PortMap: m.PortMap,
  548. // Label: m.Label,
  549. // EnableUPNP: m.EnableUPNP,
  550. // UdpPorts: m.Udp,
  551. // TcpPorts: m.Tcp,
  552. // Envs: m.Envs,
  553. // Volumes: m.Volumes,
  554. // Position: m.Position,
  555. // NetModel: m.NetworkModel,
  556. // Restart: m.Restart,
  557. // CpuShares: m.CpuShares,
  558. // Memory: m.Memory,
  559. // Devices: m.Devices,
  560. // Rely: rely,
  561. // Origin: "custom",
  562. // }
  563. // if m.NetworkModel == "host" {
  564. // m.PortMap = m.Port
  565. // }
  566. // service.MyService.App().SaveContainer(md)
  567. //
  568. // }()
  569. //
  570. // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: id})
  571. //
  572. //}
  573. // @Summary 卸载app
  574. // @Produce application/json
  575. // @Accept multipart/form-data
  576. // @Tags app
  577. // @Param id path string true "容器id"
  578. // @Security ApiKeyAuth
  579. // @Success 200 {string} string "ok"
  580. // @Router /app/uninstall/{id} [delete]
  581. func UnInstallApp(c *gin.Context) {
  582. appId := c.Param("id")
  583. if len(appId) == 0 {
  584. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
  585. return
  586. }
  587. info := service.MyService.App().GetUninstallInfo(appId)
  588. //step:停止容器
  589. err := service.MyService.Docker().DockerContainerStop(appId)
  590. if err != nil {
  591. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
  592. return
  593. }
  594. //step:删除容器
  595. err = service.MyService.Docker().DockerContainerRemove(appId)
  596. if err != nil {
  597. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
  598. return
  599. }
  600. //存在镜像正在使用的情况
  601. // step:删除镜像
  602. service.MyService.Docker().DockerImageRemove(info.Image + ":" + info.Version)
  603. //step: 删除本地数据
  604. service.MyService.App().RemoveContainerById(appId)
  605. if info.Origin != "custom" {
  606. //step: 删除文件夹
  607. service.MyService.App().DelAppConfigDir(appId)
  608. //step: 删除install log
  609. service.MyService.Notify().DelLog(appId)
  610. // for k, v := range info.Rely {
  611. //
  612. // if k == "mysql" {
  613. // docker_base.MysqlDelete(v)
  614. // service.MyService.Rely().Delete(v)
  615. // }
  616. // }
  617. //if info.EnableUPNP {
  618. // upnp, err := upnp2.Gateway()
  619. // if err == nil {
  620. // for _, p := range info.Ports {
  621. // if p.Protocol == "udp" {
  622. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  623. // upnp.LocalHost = ip_helper2.GetLoclIp()
  624. // tComment, _ := strconv.Atoi(p.CommendPort)
  625. // upnp.DelPortMapping(tComment, "UDP")
  626. // time.Sleep(time.Millisecond * 200)
  627. // } else if p.Protocol == "tcp" {
  628. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  629. // upnp.LocalHost = ip_helper2.GetLoclIp()
  630. // tComment, _ := strconv.Atoi(p.CommendPort)
  631. // upnp.DelPortMapping(tComment, "TCP")
  632. // time.Sleep(time.Millisecond * 200)
  633. // } else if p.Protocol == "both" {
  634. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  635. // upnp.LocalHost = ip_helper2.GetLoclIp()
  636. // tComment, _ := strconv.Atoi(p.CommendPort)
  637. // upnp.DelPortMapping(tComment, "UDP")
  638. //
  639. // upnp.DelPortMapping(tComment, "TCP")
  640. // time.Sleep(time.Millisecond * 200)
  641. // }
  642. // }
  643. // }
  644. //}
  645. }
  646. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
  647. }
  648. // @Summary 修改app状态
  649. // @Produce application/json
  650. // @Accept multipart/form-data
  651. // @Tags app
  652. // @Param id path string true "appid"
  653. // @Param state query string false "是否停止 start stop restart"
  654. // @Security ApiKeyAuth
  655. // @Success 200 {string} string "ok"
  656. // @Router /app/state/{id} [put]
  657. func ChangAppState(c *gin.Context) {
  658. appId := c.Param("id")
  659. state := c.DefaultPostForm("state", "stop")
  660. var err error
  661. if state == "stop" {
  662. err = service.MyService.Docker().DockerContainerStop(appId)
  663. } else if state == "start" {
  664. err = service.MyService.Docker().DockerContainerStart(appId)
  665. } else if state == "restart" {
  666. err = service.MyService.Docker().DockerContainerStop(appId)
  667. err = service.MyService.Docker().DockerContainerStart(appId)
  668. }
  669. if err != nil {
  670. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
  671. return
  672. }
  673. info, err := service.MyService.App().GetContainerInfo(appId)
  674. if err != nil {
  675. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
  676. return
  677. }
  678. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info.State})
  679. }
  680. // @Summary 查看容器日志
  681. // @Produce application/json
  682. // @Accept application/json
  683. // @Tags app
  684. // @Param id path string true "appid"
  685. // @Security ApiKeyAuth
  686. // @Success 200 {string} string "ok"
  687. // @Router /app/logs/{id} [get]
  688. func ContainerLog(c *gin.Context) {
  689. appId := c.Param("id")
  690. log, _ := service.MyService.Docker().DockerContainerLog(appId)
  691. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: log})
  692. }
  693. // @Summary 获取安装进度
  694. // @Produce application/json
  695. // @Accept application/json
  696. // @Tags app
  697. // @Param id path string true "容器id"
  698. // @Security ApiKeyAuth
  699. // @Success 200 {string} string "ok"
  700. // @Router /app/speed/{id} [get]
  701. func GetInstallSpeed(c *gin.Context) {
  702. id := c.Param("id")
  703. b := service.MyService.Notify().GetLog(id)
  704. b.Id = b.CustomId
  705. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
  706. }
  707. // @Summary 获取容器状态
  708. // @Produce application/json
  709. // @Accept application/json
  710. // @Tags app
  711. // @Param id path string true "容器id"
  712. // @Param type query string false "type=1"
  713. // @Security ApiKeyAuth
  714. // @Success 200 {string} string "ok"
  715. // @Router /app/state/{id} [get]
  716. func GetContainerState(c *gin.Context) {
  717. id := c.Param("id")
  718. t := c.DefaultQuery("type", "0")
  719. containerInfo, e := service.MyService.App().GetSimpleContainerInfo(id)
  720. if e != nil {
  721. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: e.Error()})
  722. return
  723. }
  724. var data = make(map[string]interface{})
  725. data["state"] = containerInfo.State
  726. if t == "1" {
  727. appInfo := service.MyService.App().GetAppDBInfo(id)
  728. data["app"] = appInfo
  729. }
  730. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
  731. }
  732. // @Summary 更新设置
  733. // @Produce application/json
  734. // @Accept multipart/form-data
  735. // @Tags app
  736. // @Param id path string true "容器id"
  737. // @Param shares formData string false "cpu权重"
  738. // @Param mem formData string false "内存大小MB"
  739. // @Param restart formData string false "重启策略"
  740. // @Param label formData string false "应用名称"
  741. // @Param position formData bool true "是否放到首页"
  742. // @Security ApiKeyAuth
  743. // @Success 200 {string} string "ok"
  744. // @Router /app/update/{id}/setting [put]
  745. func UpdateSetting(c *gin.Context) {
  746. id := c.Param("id")
  747. const CUSTOM = "custom"
  748. m := model.CustomizationPostData{}
  749. c.BindJSON(&m)
  750. if len(id) == 0 {
  751. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
  752. return
  753. }
  754. var cpd model.CustomizationPostData
  755. copier.Copy(&cpd, &m)
  756. appInfo := service.MyService.App().GetAppDBInfo(id)
  757. var containerId string
  758. containerId = appInfo.ContainerId
  759. service.MyService.Docker().DockerContainerStop(id)
  760. portMap, _ := strconv.Atoi(m.PortMap)
  761. if !port2.IsPortAvailable(portMap, "tcp") {
  762. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap})
  763. return
  764. }
  765. for _, u := range m.Ports {
  766. if u.Protocol == "udp" {
  767. t, _ := strconv.Atoi(u.CommendPort)
  768. if !port2.IsPortAvailable(t, "udp") {
  769. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  770. return
  771. }
  772. } else if u.Protocol == "tcp" {
  773. te, _ := strconv.Atoi(u.CommendPort)
  774. if !port2.IsPortAvailable(te, "tcp") {
  775. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  776. return
  777. }
  778. } else if u.Protocol == "both" {
  779. t, _ := strconv.Atoi(u.CommendPort)
  780. if !port2.IsPortAvailable(t, "udp") {
  781. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  782. return
  783. }
  784. te, _ := strconv.Atoi(u.CommendPort)
  785. if !port2.IsPortAvailable(te, "tcp") {
  786. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
  787. return
  788. }
  789. }
  790. }
  791. if !reflect.DeepEqual(m.Ports, appInfo.Ports) || !reflect.DeepEqual(m.Envs, appInfo.Envs) || !reflect.DeepEqual(m.Volumes, appInfo.Volumes) || m.PortMap != appInfo.PortMap {
  792. service.MyService.Docker().DockerContainerRemove(id)
  793. var err error
  794. containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, id, cpd, appInfo.NetModel)
  795. if err != nil {
  796. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
  797. return
  798. }
  799. } else if !reflect.DeepEqual(m.Devices, appInfo.Devices) || m.CpuShares != appInfo.CpuShares || m.Memory != appInfo.Memory || m.Restart != appInfo.Restart {
  800. service.MyService.Docker().DockerContainerUpdate(cpd, id)
  801. }
  802. err := service.MyService.Docker().DockerContainerStart(id)
  803. if err != nil {
  804. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
  805. return
  806. }
  807. //更新upnp
  808. if m.Origin != CUSTOM {
  809. //if appInfo.EnableUPNP != appInfo.EnableUPNP {
  810. // if appInfo.EnableUPNP {
  811. // upnp, err := upnp2.Gateway()
  812. // if err == nil {
  813. //
  814. // for _, p := range appInfo.Ports {
  815. // if p.Protocol == "udp" {
  816. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  817. // upnp.LocalHost = ip_helper2.GetLoclIp()
  818. // tComment, _ := strconv.Atoi(p.CommendPort)
  819. // upnp.AddPortMapping(tComment, tComment, "UDP")
  820. // time.Sleep(time.Millisecond * 200)
  821. // } else if p.Protocol == "tcp" {
  822. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  823. // upnp.LocalHost = ip_helper2.GetLoclIp()
  824. // tComment, _ := strconv.Atoi(p.CommendPort)
  825. // upnp.AddPortMapping(tComment, tComment, "TCP")
  826. // time.Sleep(time.Millisecond * 200)
  827. // } else if p.Protocol == "both" {
  828. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  829. // upnp.LocalHost = ip_helper2.GetLoclIp()
  830. // tComment, _ := strconv.Atoi(p.CommendPort)
  831. // upnp.AddPortMapping(tComment, tComment, "UDP")
  832. // time.Sleep(time.Millisecond * 200)
  833. //
  834. // upnp.AddPortMapping(tComment, tComment, "TCP")
  835. // time.Sleep(time.Millisecond * 200)
  836. // }
  837. // }
  838. // }
  839. // } else {
  840. // upnp, err := upnp2.Gateway()
  841. // if err == nil {
  842. // for _, p := range appInfo.Ports {
  843. // if p.Protocol == "udp" {
  844. //
  845. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  846. // upnp.LocalHost = ip_helper2.GetLoclIp()
  847. // tComment, _ := strconv.Atoi(p.CommendPort)
  848. // upnp.DelPortMapping(tComment, "UDP")
  849. // time.Sleep(time.Millisecond * 200)
  850. // } else if p.Protocol == "tcp" {
  851. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  852. // upnp.LocalHost = ip_helper2.GetLoclIp()
  853. // tComment, _ := strconv.Atoi(p.CommendPort)
  854. // upnp.DelPortMapping(tComment, "TCP")
  855. // time.Sleep(time.Millisecond * 200)
  856. // } else if p.Protocol == "both" {
  857. // upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
  858. // upnp.LocalHost = ip_helper2.GetLoclIp()
  859. // tComment, _ := strconv.Atoi(p.CommendPort)
  860. // upnp.DelPortMapping(tComment, "UDP")
  861. // time.Sleep(time.Millisecond * 200)
  862. //
  863. // upnp.DelPortMapping(tComment, "TCP")
  864. // time.Sleep(time.Millisecond * 200)
  865. // }
  866. // }
  867. // }
  868. // }
  869. //}
  870. }
  871. //如果容器端口均未修改,这不进行处理
  872. portsStr, _ := json2.Marshal(m.Ports)
  873. envsStr, _ := json2.Marshal(m.Envs)
  874. volumesStr, _ := json2.Marshal(m.Volumes)
  875. devicesStr, _ := json2.Marshal(m.Devices)
  876. appInfo.ContainerId = containerId
  877. appInfo.PortMap = m.PortMap
  878. appInfo.Label = m.Label
  879. appInfo.Ports = string(portsStr)
  880. appInfo.Envs = string(envsStr)
  881. appInfo.Icon = m.Icon
  882. appInfo.Volumes = string(volumesStr)
  883. appInfo.Devices = string(devicesStr)
  884. appInfo.Position = m.Position
  885. appInfo.EnableUPNP = m.EnableUPNP
  886. appInfo.Restart = m.Restart
  887. appInfo.Memory = m.Memory
  888. appInfo.CpuShares = m.CpuShares
  889. appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  890. service.MyService.App().UpdateApp(appInfo)
  891. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
  892. }
  893. // @Summary 获取容器详情
  894. // @Produce application/json
  895. // @Accept application/json
  896. // @Tags app
  897. // @Param id path string true "appid"
  898. // @Security ApiKeyAuth
  899. // @Success 200 {string} string "ok"
  900. // @Router /app/info/{id} [get]
  901. func ContainerInfo(c *gin.Context) {
  902. appId := c.Param("id")
  903. appInfo := service.MyService.App().GetAppDBInfo(appId)
  904. containerInfo, _ := service.MyService.Docker().DockerContainerStats(appId)
  905. var cpuModel = "arm"
  906. if cpu := service.MyService.ZiMa().GetCpuInfo(); len(cpu) > 0 {
  907. if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
  908. cpuModel = "intel"
  909. } else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
  910. cpuModel = "amd"
  911. }
  912. }
  913. info, err := service.MyService.Docker().DockerContainerInfo(appId)
  914. if err != nil {
  915. //todo 需要自定义错误
  916. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
  917. return
  918. }
  919. con := struct {
  920. Status string `json:"status"`
  921. StartedAt string `json:"started_at"`
  922. CPUShares int64 `json:"cpu_shares"`
  923. Memory int64 `json:"memory"`
  924. Restart string `json:"restart"`
  925. }{Status: info.State.Status, StartedAt: info.State.StartedAt, CPUShares: info.HostConfig.CPUShares, Memory: info.HostConfig.Memory >> 20, Restart: info.HostConfig.RestartPolicy.Name}
  926. data := make(map[string]interface{}, 5)
  927. data["app"] = appInfo
  928. data["cpu"] = cpuModel
  929. data["memory"] = service.MyService.ZiMa().GetMemInfo().Total
  930. data["container"] = json2.RawMessage(containerInfo)
  931. data["info"] = con
  932. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
  933. }
  934. // @Summary 获取安装所需要的数据
  935. // @Produce application/json
  936. // @Accept application/json
  937. // @Tags app
  938. // @Security ApiKeyAuth
  939. // @Success 200 {string} string "ok"
  940. // @Router /app/install/config [get]
  941. func GetDockerInstallConfig(c *gin.Context) {
  942. networks := service.MyService.Docker().DockerNetworkModelList()
  943. data := make(map[string]interface{}, 2)
  944. list := []map[string]string{}
  945. for _, network := range networks {
  946. if network.Driver != "null" {
  947. list = append(list, map[string]string{"name": network.Name, "driver": network.Driver, "id": network.ID})
  948. }
  949. }
  950. data["networks"] = list
  951. data["memory"] = service.MyService.ZiMa().GetMemInfo()
  952. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
  953. }
  954. // @Summary 获取依赖数据
  955. // @Produce application/json
  956. // @Accept application/json
  957. // @Tags app
  958. // @Param id path string true "rely id"
  959. // @Security ApiKeyAuth
  960. // @Success 200 {string} string "ok"
  961. // @Router /app/rely/{id}/info [get]
  962. func ContainerRelyInfo(c *gin.Context) {
  963. id := c.Param("id")
  964. appInfo := service.MyService.Rely().GetInfo(id)
  965. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: appInfo})
  966. }
  967. // @Summary 获取可更新数据
  968. // @Produce application/json
  969. // @Accept application/json
  970. // @Tags app
  971. // @Param id path string true "appid"
  972. // @Security ApiKeyAuth
  973. // @Success 200 {string} string "ok"
  974. // @Router /app/update/{id}/info [get]
  975. func ContainerUpdateInfo(c *gin.Context) {
  976. appId := c.Param("id")
  977. appInfo := service.MyService.App().GetAppDBInfo(appId)
  978. info, err := service.MyService.Docker().DockerContainerInfo(appId)
  979. if err != nil {
  980. //todo 需要自定义错误
  981. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
  982. return
  983. }
  984. var port model.PortArrey
  985. json2.Unmarshal([]byte(appInfo.Ports), &port)
  986. var envs model.EnvArrey
  987. json2.Unmarshal([]byte(appInfo.Envs), &envs)
  988. var vol model.PathArrey
  989. json2.Unmarshal([]byte(appInfo.Volumes), &vol)
  990. var dir model.PathArrey
  991. json2.Unmarshal([]byte(appInfo.Devices), &dir)
  992. //volumesStr, _ := json2.Marshal(m.Volumes)
  993. //devicesStr, _ := json2.Marshal(m.Devices)
  994. m := model.CustomizationPostData{}
  995. m.Index = appInfo.Index
  996. m.Icon = appInfo.Icon
  997. m.Ports = port
  998. m.Image = appInfo.Image + ":" + appInfo.Version
  999. m.Origin = appInfo.Origin
  1000. m.NetworkModel = appInfo.NetModel
  1001. m.Description = appInfo.Description
  1002. m.Label = appInfo.Label
  1003. m.PortMap = appInfo.PortMap
  1004. m.Devices = dir //appInfo.Devices
  1005. m.Envs = envs
  1006. m.Memory = info.HostConfig.Memory >> 20
  1007. m.CpuShares = info.HostConfig.CPUShares
  1008. m.Volumes = vol //appInfo.Volumes
  1009. m.Restart = info.HostConfig.RestartPolicy.Name
  1010. m.EnableUPNP = appInfo.EnableUPNP
  1011. m.Position = appInfo.Position
  1012. c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
  1013. }
  1014. ////准备安装(暂时不需要)
  1015. //func ReadyInstall(c *gin.Context) {
  1016. // _, tcp, udp := service.MyService.GetManifestJsonByRepo()
  1017. // data := make(map[string]interface{}, 2)
  1018. // if t := gjson.Parse(tcp).Array(); len(t) > 0 {
  1019. // //tcpList := []model.TcpPorts{}
  1020. // //e := json2.Unmarshal([]byte(tcp), tcpList)
  1021. // //if e!=nil {
  1022. // // return
  1023. // //}
  1024. // //for _, port := range tcpList {
  1025. // // if port.ContainerPort>0&&port.ExtranetPort {
  1026. // //
  1027. // // }
  1028. // //}
  1029. // var inarr []interface{}
  1030. // for _, result := range t {
  1031. //
  1032. // var p int
  1033. // ok := true
  1034. // for ok {
  1035. // p, _ = port.GetAvailablePort()
  1036. // ok = !port.IsPortAvailable(p)
  1037. // }
  1038. // pm := model.PortMap{gjson.Get(result.Raw, "container_port").Int(), p}
  1039. // inarr = append(inarr, pm)
  1040. // }
  1041. // data["tcp"] = inarr
  1042. // }
  1043. // if u := gjson.Parse(udp).Array(); len(u) > 0 {
  1044. // //udpList := []model.UdpPorts{}
  1045. // //e := json2.Unmarshal([]byte(udp), udpList)
  1046. // //if e != nil {
  1047. // // return
  1048. // //}
  1049. // var inarr []model.PortMap
  1050. // for _, result := range u {
  1051. // var p int
  1052. // ok := true
  1053. // for ok {
  1054. // p, _ = port.GetAvailablePort()
  1055. // ok = !port.IsPortAvailable(p)
  1056. // }
  1057. // pm := model.PortMap{gjson.Get(result.Raw, "container_port").Int(), p}
  1058. // inarr = append(inarr, pm)
  1059. // }
  1060. // data["udp"] = inarr
  1061. // }
  1062. // c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
  1063. //}