init commit

This commit is contained in:
sianao 2025-04-09 15:52:24 +08:00
parent d1c5fb1162
commit a5b87653a3
31 changed files with 718 additions and 24 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
.idea/flores.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/flores.iml" filepath="$PROJECT_DIR$/.idea/flores.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

3
config/const.go Normal file
View File

@ -0,0 +1,3 @@
package config
const Entrypoint = "http://127.0.0.1:8888"

8
go.mod
View File

@ -4,7 +4,10 @@ go 1.22.8
toolchain go1.23.4
require github.com/gin-gonic/gin v1.10.0
require (
github.com/gin-gonic/gin v1.10.0
github.com/golang-jwt/jwt/v5 v5.2.2
)
require (
github.com/bytedance/sonic v1.11.6 // indirect
@ -26,6 +29,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/samber/lo v1.49.1 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
@ -33,7 +37,7 @@ require (
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

98
go.sum Normal file
View File

@ -0,0 +1,98 @@
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -0,0 +1,68 @@
package containers
import (
"bytes"
"encoding/json"
"floares/config"
"fmt"
"io"
"log"
"net/http"
)
type Create struct {
Image string `json:"image,required"`
Name string `json:"name,omitempty"`
}
type CreateJson struct {
Cause string `json:"cause"`
Message string `json:"message"`
Response int `json:"response"`
Id string `json:"Id,omitempty"`
Warning []string `json:"Warnings,omitempty"`
}
type create struct {
Image string `json:"image"`
}
func (c *Create) Create() (string, error) {
var container create
container.Image = c.Image
str, err := json.Marshal(container)
if err != nil {
log.Println(err)
return "", err
}
log.Println(string(str))
req, _ := http.NewRequest(http.MethodPost, config.Entrypoint+"/v2.1.2/libpod/containers/create", bytes.NewBuffer(str))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Println(err)
return "", err
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
log.Println(string(b))
var createJson CreateJson
err = json.NewDecoder(resp.Body).Decode(&createJson)
if err != nil {
log.Println(createJson)
log.Println(err)
return "", err
}
log.Println(createJson)
startContainer(createJson.Id)
return createJson.Id, nil
}
func startContainer(id string) error {
post, err := http.Post(fmt.Sprintf("/%s/libpod/containers/%s/start", config.Entrypoint, id), "application/json", nil)
if err != nil {
return err
}
bytes, err := io.ReadAll(post.Body)
log.Println(string(bytes))
return err
}

View File

@ -0,0 +1,59 @@
package containers
import (
"encoding/json"
"floares/config"
"log"
"net/http"
"strings"
"time"
)
type ListContainers struct {
Id string `json:"id"`
Name string `json:"name"`
Image string `json:"image"`
Created string `json:"created"`
Ports []interface{} `json:"ports"`
State string `json:"state"`
}
type Containers struct {
Id string `json:"Id"`
Names []string `json:"Names"`
Image string `json:"Image"`
ImageID string `json:"ImageID"`
Command string `json:"Command"`
Created int `json:"Created"`
//Ports []interface{} `json:"Ports"`
State string `json:"State"`
Status string `json:"Status"`
}
func List() []ListContainers {
var containers []Containers
req, err := http.NewRequest(http.MethodGet, config.Entrypoint+"/containers/json?all=true", nil)
if err != nil {
log.Println("request for containers list error:", err)
return []ListContainers{}
}
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("request for containers list error:", err)
return []ListContainers{}
}
err = json.NewDecoder(res.Body).Decode(&containers)
if err != nil {
log.Println("json decode container list error:", err)
}
var list []ListContainers
for _, container := range containers {
list = append(list, ListContainers{
Id: container.Id,
Name: strings.TrimPrefix(container.Names[0], "/"),
Image: container.Image,
Created: time.Unix(int64(container.Created), 0).Format(time.DateTime),
State: container.State,
})
}
return list
}

41
lib/http/images/delete.go Normal file
View File

@ -0,0 +1,41 @@
package images
import (
"context"
"encoding/json"
"floares/config"
"fmt"
"log"
"net/http"
)
type DeleteRsp struct {
Cause string `json:"cause"` //cause image is in use by a container
Message string `json:"message"`
Response int `json:"response"`
}
type DeleteRsult struct {
Code int `json:"code"`
Error string `json:"err,omitempty"`
}
func Delete(id string) DeleteRsult {
req, _ := http.NewRequestWithContext(context.Background(), http.MethodDelete, config.Entrypoint+fmt.Sprintf("/images/%s", id), nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return DeleteRsult{
Error: err.Error(),
}
}
var deleteRsult DeleteRsp
var response DeleteRsult
response.Code = resp.StatusCode
_ = json.NewDecoder(resp.Body).Decode(&deleteRsult)
log.Println(deleteRsult)
if deleteRsult.Cause != "" {
return DeleteRsult{
Error: deleteRsult.Cause,
}
}
return response
}

View File

@ -1 +1,40 @@
package images
import (
"encoding/json"
"floares/config"
"floares/lib/model"
"net/http"
"strconv"
"time"
)
type Image struct {
Id string `json:"id"`
Name string `json:"name"`
Tag string `json:"tag"`
Digest string `json:"digest"`
CreatedAt string `json:"created_at"`
Size string `json:"size"`
}
func List() []Image {
var images []model.Image
req, _ := http.NewRequest(http.MethodGet, config.Entrypoint+"/images/json", nil)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(&images)
var imagesList []Image
for _, v := range images {
imagesList = append(imagesList, Image{
Id: v.Id[7:],
Name: v.Names[0],
Tag: v.RepoTags[0],
Digest: v.Digest,
CreatedAt: time.Unix(int64(v.Created), 0).Format(time.DateTime),
Size: strconv.Itoa(v.Size/1024/1024) + " MB",
})
}
return imagesList
}

44
lib/http/images/pull.go Normal file
View File

@ -0,0 +1,44 @@
package images
import (
"context"
"encoding/json"
"floares/config"
"fmt"
"io"
"log"
"net/http"
)
type PullRsp struct {
Images []string `json:"images"`
Id string `json:"id"`
Error string `json:"errr,omitempty"`
Info string `json:"info,omitempty"`
}
func Pull(ref string) PullRsp {
var pull PullRsp
req, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, config.Entrypoint+fmt.Sprintf("/v2.2.2/libpod/images/pull?reference=%s&quiet=true", ref), nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return PullRsp{
Error: err.Error(),
}
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.Printf("Failed to close response body: %v", err)
}
}(resp.Body)
if resp.StatusCode != http.StatusOK {
return PullRsp{
Error: "status code " + resp.Status,
}
}
_ = json.NewDecoder(resp.Body).Decode(&pull)
return pull
}

View File

@ -2,13 +2,15 @@ package network
import (
"encoding/json"
"floares/config"
"floares/lib/model"
"log"
"net/http"
"time"
)
func ListJsons() []model.NetWorkJson {
req, _ := http.NewRequest("GET", "http://127.0.0.1:8888/networks", nil)
req, _ := http.NewRequest("GET", config.Entrypoint+"/networks", nil)
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("request for network list error:", err)
@ -18,3 +20,23 @@ func ListJsons() []model.NetWorkJson {
err = json.NewDecoder(res.Body).Decode(&result)
return result
}
func ListNetwork() []model.NetWork {
var result []model.NetWork
for _, v := range ListJsons() {
conf := v.IPAM.Config
var ipam []model.Config
for _, val := range conf {
ipam = append(ipam, model.Config{
Subnet: val.Subnet, Gateway: val.Gateway,
})
}
result = append(result, model.NetWork{
Name: v.Name,
Id: v.Id,
Created: v.Created.Format(time.DateTime),
Driver: v.Driver,
IPAM: ipam,
})
}
return result
}

View File

@ -2,13 +2,14 @@ package system
import (
"encoding/json"
"floares/config"
"floares/lib/model"
"log"
"net/http"
)
func Version() model.Version {
req, _ := http.NewRequest("GET", "http://127.0.0.1:8888/version", nil)
req, _ := http.NewRequest("GET", config.Entrypoint+"/version", nil)
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("request for version list error:", err)

View File

@ -2,13 +2,14 @@ package volume
import (
"encoding/json"
"floares/config"
"floares/lib/model"
"log"
"net/http"
)
func ListJsons() model.VolumesJson {
req, _ := http.NewRequest("GET", "http://127.0.0.1:8888/volumes", nil)
req, _ := http.NewRequest("GET", config.Entrypoint+"/volumes", nil)
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("request for volume list error:", err)

15
lib/model/images.go Normal file
View File

@ -0,0 +1,15 @@
package model
type Image struct {
Id string `json:"Id"`
RepoTags []string `json:"RepoTags"`
Created int `json:"Created"`
Size int `json:"Size"`
SharedSize int `json:"SharedSize"`
VirtualSize int `json:"VirtualSize"`
Labels *struct {
Maintainer string `json:"maintainer,omitempty"`
} `json:"Labels"`
Digest string `json:"Digest"`
Names []string `json:"Names"`
}

View File

@ -33,3 +33,15 @@ type NetWorkJson struct {
Labels struct {
} `json:"Labels"`
}
type NetWork struct {
Name string `json:"name"`
Id string `json:"id"`
Created string `json:"created"`
Driver string `json:"driver"`
IPAM []Config `json:"ipam"`
}
type Config struct {
Subnet string `json:"subnet"`
Gateway string `json:"gateway"`
}

View File

@ -1,18 +1,13 @@
package model
import "time"
type VolumesJson struct {
Volumes []struct {
CreatedAt time.Time `json:"CreatedAt"`
Driver string `json:"Driver"`
Labels struct {
} `json:"Labels"`
Mountpoint string `json:"Mountpoint"`
Name string `json:"Name"`
Options struct {
} `json:"Options"`
Scope string `json:"Scope"`
} `json:"Volumes"`
Warnings []interface{} `json:"Warnings"`
Volumes []Volume `json:"volumes"`
}
type Volume struct {
Driver string `json:"driver"`
Labels struct {
} `json:"labels"`
Mountpoint string `json:"mountpoint"`
Name string `json:"name"`
Scope string `json:"scope"`
}

41
main.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"floares/service/auth"
"floares/service/containers"
"floares/service/images"
"floares/service/network"
"floares/service/system"
"floares/service/volume"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.Use(func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH")
c.Header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Content-Type,Authorization")
c.Header("Access-Control-Expose-Headers", "Content-Length")
c.Header("Access-Control-Allow-Credentials", "true")
if c.Request.Method == "OPTIONS" {
c.Status(http.StatusNoContent)
c.Abort()
}
return
})
a := r.Group("/api/auth")
a.POST("/sign-in", auth.Sign)
a.GET("/me", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
})
a.POST("/sign-up", auth.Sign)
system.RegisterRouter(r.Group("/system"))
containers.RegisterRouter(r.Group("/containers"))
images.RegisterRouter(r.Group("/images"))
network.RegisterRouter(r.Group("/network"))
volume.RegisterRouter(r.Group("/volumes"))
r.Run()
}

View File

@ -1,24 +1,70 @@
package auth
import (
"crypto/sha1"
"encoding/base64"
"github.com/gin-gonic/gin"
"log"
"github.com/golang-jwt/jwt/v5"
"net/http"
"time"
)
type SignReq struct {
Email string `json:"email"`
Password string `json:"password"`
}
type User struct {
Id string `json:"id"`
DisplayName string `json:"displayName"`
PhotoURL string `json:"photoURL"`
PhoneNumber string `json:"phoneNumber"`
Country string `json:"country"`
Address string `json:"address"`
State string `json:"state"`
City string `json:"city"`
ZipCode string `json:"zipCode"`
About string `json:"about"`
Role string `json:"role"`
IsPublic bool `json:"isPublic"`
Email string `json:"email"`
Password string `json:"password"`
}
func Sign(c *gin.Context) {
var req SignReq
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
jwt.
c.JSON(http.StatusOK, gin.H{
"data": "hello world",
token, _ := GenToken(req.Email)
c.JSON(http.StatusOK, gin.H{
"accessToken": token,
"user": User{},
})
log.Println(req)
}
type Token struct {
Token string `json:"token"`
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
IssuedAt string `json:"issued_at"`
}
func DefaultToken(ip string) Token {
acc := sha1.Sum([]byte(ip))
access := base64.StdEncoding.EncodeToString(acc[:])
return Token{
Token: access,
AccessToken: access,
ExpiresIn: 300,
IssuedAt: time.Now().Format("2006-01-02T15:04:05.999999999Z"),
}
}
func GenToken(u string) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user": u,
"nbf": time.Now().Unix(),
"exp": time.Now().Add(time.Minute * 300).Unix(),
})
return token.SignedString([]byte("fasthub-center"))
}

View File

@ -0,0 +1,35 @@
package containers
import (
"floares/lib/http/containers"
"github.com/gin-gonic/gin"
)
func ListContainers(c *gin.Context) {
container := containers.List()
c.JSON(200, gin.H{
"data": container,
})
}
func CreateContainer(c *gin.Context) {
var create containers.Create
if err := c.BindJSON(&create); err != nil {
c.JSON(200, gin.H{
"data": nil,
"error": err.Error(),
})
return
}
id, err := create.Create()
if err != nil {
c.JSON(200, gin.H{
"data": nil,
"error": err.Error(),
})
return
}
c.JSON(200, gin.H{
"data": id,
})
}

View File

@ -0,0 +1,9 @@
package containers
import "github.com/gin-gonic/gin"
func RegisterRouter(r *gin.RouterGroup) {
r.GET("/all", ListContainers)
r.POST("/create", CreateContainer)
}

43
service/images/base.go Normal file
View File

@ -0,0 +1,43 @@
package images
import (
"floares/lib/http/images"
"github.com/gin-gonic/gin"
"net/http"
)
func ListImages(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"data": images.List(),
"code": http.StatusOK,
})
}
func PullImage(c *gin.Context) {
type Ref struct {
Ref string `json:"ref"`
}
var ref Ref
if err := c.ShouldBind(&ref); err != nil {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusBadRequest,
"data": gin.H{
"err": err.Error(),
},
})
return
}
c.JSON(http.StatusOK, gin.H{
"data": images.Pull(ref.Ref),
"code": http.StatusOK,
})
}
func Delete(c *gin.Context) {
result := images.Delete(c.Param("id"))
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"err": result.Error,
})
}

10
service/images/router.go Normal file
View File

@ -0,0 +1,10 @@
package images
import "github.com/gin-gonic/gin"
func RegisterRouter(c *gin.RouterGroup) {
c.GET("/", ListImages)
c.POST("/pull", PullImage)
c.DELETE("/:id", Delete)
}

14
service/network/list.go Normal file
View File

@ -0,0 +1,14 @@
package network
import (
"floares/lib/http/network"
"github.com/gin-gonic/gin"
)
func ListNetwork(c *gin.Context) {
net := network.ListNetwork()
c.JSON(200, gin.H{
"data": net,
"code": 200,
})
}

View File

@ -0,0 +1,7 @@
package network
import "github.com/gin-gonic/gin"
func RegisterRouter(r *gin.RouterGroup) {
r.GET("/", ListNetwork)
}

26
service/system/basic.go Normal file
View File

@ -0,0 +1,26 @@
package system
import (
"floares/lib/http/network"
"floares/lib/http/system"
"floares/lib/http/volume"
"floares/lib/model"
"github.com/gin-gonic/gin"
)
func BasicInfo(c *gin.Context) {
bas := system.Info()
version := system.Version()
c.JSON(200, model.BasicInfo{
Uptime: bas.Uptime,
DefaultRuntime: bas.DefaultRuntime,
NCPU: bas.NCPU,
MemTotal: bas.MemTotal,
OperatingSystem: bas.OperatingSystem,
Images: bas.Images,
Containers: bas.Containers,
Platform: version.Platform,
Volumes: len(volume.ListJsons().Volumes),
Networks: len(network.ListJsons()),
})
}

9
service/system/router.go Normal file
View File

@ -0,0 +1,9 @@
package system
import "github.com/gin-gonic/gin"
func RegisterRouter(r *gin.RouterGroup) {
r.GET("/ping", BasicInfo)
r.GET("/basic", BasicInfo)
}

14
service/volume/list.go Normal file
View File

@ -0,0 +1,14 @@
package volume
import (
"floares/lib/http/volume"
"github.com/gin-gonic/gin"
"net/http"
)
func List(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"data": volume.ListJsons(),
"code": http.StatusOK,
})
}

7
service/volume/router.go Normal file
View File

@ -0,0 +1,7 @@
package volume
import "github.com/gin-gonic/gin"
func RegisterRouter(c *gin.RouterGroup) {
c.GET("/", List)
}

BIN
tmp/runner-build Executable file

Binary file not shown.