begin move to go-restful

This commit is contained in:
Mikaël Cluseau 2019-02-01 18:28:08 +11:00
parent 92d3142d96
commit f4f285d0dc
8 changed files with 228 additions and 8 deletions

View File

@ -13,7 +13,6 @@ import (
"path/filepath"
"regexp"
"strings"
"time"
"novit.nc/direktil/pkg/localconfig"
)
@ -273,7 +272,7 @@ func uploadConfig(w http.ResponseWriter, r *http.Request) {
}
err = func() (err error) {
backupPath := filepath.Join(archivesPath, "config."+time.Now().Format(time.RFC3339)+".yaml.gz")
backupPath := filepath.Join(archivesPath, "config."+ulid()+".yaml.gz")
bck, err := os.Create(backupPath)
if err != nil {

View File

@ -6,7 +6,10 @@ import (
"net/http"
"path/filepath"
restful "github.com/emicklei/go-restful"
"novit.nc/direktil/pkg/cas"
"novit.nc/direktil/local-server/pkg/apiutils"
)
const (
@ -30,16 +33,19 @@ func main() {
}
casStore = cas.NewDir(filepath.Join(*dataDir, "cache"))
go casCleaner()
apiutils.Setup(func() {
restful.Add(buildWS())
})
// by default, serve a host resource by its IP
http.HandleFunc("/", serveHostByIP)
//http.HandleFunc("/", serveHostByIP)
http.HandleFunc("/configs", uploadConfig)
http.HandleFunc("/hosts", serveHosts)
http.HandleFunc("/hosts/", serveHost)
//http.HandleFunc("/hosts/", serveHost)
http.HandleFunc("/clusters", serveClusters)
http.HandleFunc("/clusters/", serveCluster)

View File

@ -0,0 +1,22 @@
package main
import (
"io"
"math/rand"
"time"
ulidp "github.com/oklog/ulid"
)
var (
ulidCtx struct{ entropy io.Reader }
)
func initUlid() {
entropy := ulidp.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0)
ulidCtx.entropy = entropy
}
func ulid() string {
return ulidp.MustNew(ulidp.Now(), ulidCtx.entropy).String()
}

View File

@ -0,0 +1,55 @@
package main
import (
"log"
"net/http"
"path"
restful "github.com/emicklei/go-restful"
)
type wsHost struct {
prefix string
getHost func(req *restful.Request) string
}
func (ws *wsHost) register(rws *restful.WebService) {
for _, what := range []string{
"boot.img",
"boot.img.gz",
"boot.img.lz4",
"boot.iso",
"boot.tar",
"config",
"initrd",
"ipxe",
"kernel",
} {
rws.Route(rws.GET(ws.prefix + "/" + what).To(ws.render))
}
}
func (ws *wsHost) render(req *restful.Request, resp *restful.Response) {
hostname := ws.getHost(req)
if hostname == "" {
http.NotFound(resp.ResponseWriter, req.Request)
return
}
cfg, err := readConfig()
if err != nil {
writeError(resp.ResponseWriter, err)
return
}
host := cfg.Host(hostname)
if host == nil {
log.Print("no host named ", hostname)
http.NotFound(resp.ResponseWriter, req.Request)
return
}
what := path.Base(req.Request.URL.Path)
renderHost(resp.ResponseWriter, req.Request, what, host, cfg)
}

View File

@ -0,0 +1,64 @@
package main
import (
"log"
"net"
"strings"
"github.com/emicklei/go-restful"
)
func buildWS() *restful.WebService {
ws := &restful.WebService{}
ws.Route(ws.POST("/configs").To(wsUploadConfig))
(&wsHost{
prefix: "",
getHost: detectHost,
}).register(ws)
(&wsHost{
prefix: "/hosts/{hostname}",
getHost: func(req *restful.Request) string {
return req.PathParameter("hostname")
},
}).register(ws)
return ws
}
func detectHost(req *restful.Request) string {
r := req.Request
remoteAddr := r.RemoteAddr
if *trustXFF {
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
remoteAddr = strings.Split(xff, ",")[0]
}
}
hostIP, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
hostIP = remoteAddr
}
cfg, err := readConfig()
if err != nil {
return ""
}
host := cfg.HostByIP(hostIP)
if host == nil {
log.Print("no host found for IP ", hostIP)
return ""
}
return host.Name
}
func wsUploadConfig(req *restful.Request, res *restful.Response) {
// TODO
}

10
go.mod
View File

@ -4,15 +4,19 @@ require (
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e
github.com/coreos/etcd v3.3.11+incompatible // indirect
github.com/emicklei/go-restful v2.8.1+incompatible
github.com/emicklei/go-restful-openapi v1.0.0
github.com/go-openapi/spec v0.18.0 // indirect
github.com/gobuffalo/events v1.2.0 // indirect
github.com/gobuffalo/meta v0.0.0-20190126124307-c8fb6f4eb5a9 // indirect
github.com/gobuffalo/packr v1.21.9 // indirect
github.com/gofrs/uuid v3.2.0+incompatible // indirect
github.com/google/certificate-transparency-go v1.0.21 // indirect
github.com/google/certificate-transparency-go v1.0.21
github.com/oklog/ulid v1.3.1
github.com/pierrec/lz4 v2.0.5+incompatible
github.com/ugorji/go/codec v0.0.0-20190128213124-ee1426cffec0 // indirect
golang.org/x/crypto v0.0.0-20190129210102-ccddf3741a0c // indirect
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
golang.org/x/crypto v0.0.0-20190129210102-ccddf3741a0c
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc // indirect
golang.org/x/tools v0.0.0-20190130015043-a06a922acc1b // indirect
gopkg.in/yaml.v2 v2.2.2

20
go.sum
View File

@ -1,5 +1,9 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
@ -24,10 +28,22 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/emicklei/go-restful v2.8.1+incompatible h1:AyDqLHbJ1quqbWr/OWDw+PlIP8ZFoTmYrGYaxzrLbNg=
github.com/emicklei/go-restful v2.8.1+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful-openapi v1.0.0 h1:ZFk3RuCl8ZmG1yUAF/mSbXRi5cuyA/k5+EpHayuuTXM=
github.com/emicklei/go-restful-openapi v1.0.0/go.mod h1:Q+bHVYfUWv1fvC4FNTsz2AVvFSsXAC7RCiWjF1Sva1A=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/spec v0.18.0 h1:aIjeyG5mo5/FrvDkpKKEGZPmF9MPHahS72mzfVqeQXQ=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/gobuffalo/buffalo v0.12.8-0.20181004233540-fac9bb505aa8/go.mod h1:sLyT7/dceRXJUxSsE813JTQtA3Eb1vjxWfo/N//vXIY=
@ -333,6 +349,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c=
@ -368,6 +386,8 @@ github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=

50
pkg/apiutils/apiutils.go Normal file
View File

@ -0,0 +1,50 @@
package apiutils
import (
"github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
)
// Prepare does the default API preparation.
func Prepare() {
restful.DefaultRequestContentType(restful.MIME_JSON)
restful.DefaultResponseContentType(restful.MIME_JSON)
restful.DefaultContainer.Router(restful.CurlyRouter{})
}
// Setup does the default API setup
func Setup(addWebServices func()) {
Prepare()
addWebServices()
SetupHealth()
SetupOpenAPI()
SetupCORSWildcard()
}
func SetupHealth() {
// TODO
}
// SetupOpenAPI creates the standard API documentation endpoint at the default location.
func SetupOpenAPI() {
SetupOpenAPIAt("/swagger.json")
}
// SetupOpenAPI creates the standard API documentation endpoint at the defined location.
func SetupOpenAPIAt(apiPath string) {
config := restfulspec.Config{
WebServices: restful.RegisteredWebServices(),
APIPath: apiPath,
}
restful.Add(restfulspec.NewOpenAPIService(config))
}
func SetupCORSWildcard() {
restful.Filter(restful.CrossOriginResourceSharing{
CookiesAllowed: true,
Container: restful.DefaultContainer,
}.Filter)
restful.Filter(restful.OPTIONSFilter())
}