allow share endpoint to return multiple frontends; more frontend selection (#110)

This commit is contained in:
Michael Quigley 2022-12-06 12:00:25 -05:00
parent 081a558ba2
commit a0c50c68e5
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
10 changed files with 134 additions and 28 deletions

View File

@ -31,17 +31,18 @@ func init() {
} }
type loopCmd struct { type loopCmd struct {
cmd *cobra.Command cmd *cobra.Command
loopers int loopers int
iterations int iterations int
statusEvery int statusEvery int
timeoutSeconds int timeoutSeconds int
minPayload int minPayload int
maxPayload int maxPayload int
minDwellMs int minDwellMs int
maxDwellMs int maxDwellMs int
minPacingMs int minPacingMs int
maxPacingMs int maxPacingMs int
frontendSelection []string
} }
func newLoopCmd() *loopCmd { func newLoopCmd() *loopCmd {
@ -62,6 +63,7 @@ func newLoopCmd() *loopCmd {
cmd.Flags().IntVar(&r.maxDwellMs, "max-dwell-ms", 1000, "Maximum dwell time in milliseconds") cmd.Flags().IntVar(&r.maxDwellMs, "max-dwell-ms", 1000, "Maximum dwell time in milliseconds")
cmd.Flags().IntVar(&r.minPacingMs, "min-pacing-ms", 0, "Minimum pacing in milliseconds") cmd.Flags().IntVar(&r.minPacingMs, "min-pacing-ms", 0, "Minimum pacing in milliseconds")
cmd.Flags().IntVar(&r.maxPacingMs, "max-pacing-ms", 0, "Maximum pacing in milliseconds") cmd.Flags().IntVar(&r.maxPacingMs, "max-pacing-ms", 0, "Maximum pacing in milliseconds")
cmd.Flags().StringArrayVar(&r.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
return r return r
} }
@ -186,6 +188,7 @@ func (l *looper) startup() {
tunnelReq.Body = &rest_model_zrok.ShareRequest{ tunnelReq.Body = &rest_model_zrok.ShareRequest{
EnvZID: l.env.ZId, EnvZID: l.env.ZId,
ShareMode: "public", ShareMode: "public",
FrontendSelection: l.cmd.frontendSelection,
BackendMode: "proxy", BackendMode: "proxy",
BackendProxyEndpoint: fmt.Sprintf("looper#%d", l.id), BackendProxyEndpoint: fmt.Sprintf("looper#%d", l.id),
AuthScheme: string(model.None), AuthScheme: string(model.None),
@ -196,7 +199,7 @@ func (l *looper) startup() {
panic(err) panic(err)
} }
l.service = tunnelResp.Payload.SvcToken l.service = tunnelResp.Payload.SvcToken
l.proxyEndpoint = tunnelResp.Payload.FrontendProxyEndpoint l.proxyEndpoint = tunnelResp.Payload.FrontendProxyEndpoints[0]
} }
func (l *looper) dwell() { func (l *looper) dwell() {

View File

@ -102,7 +102,7 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
} }
logrus.Infof("your reserved service token is '%v'", resp.Payload.SvcToken) logrus.Infof("your reserved service token is '%v'", resp.Payload.SvcToken)
if resp.Payload.FrontendProxyEndpoint != "" { for _, fpe := range resp.Payload.FrontendProxyEndpoints {
logrus.Infof("your reserved service frontend is '%v'", resp.Payload.FrontendProxyEndpoint) logrus.Infof("reserved frontend endpoint: %v", fpe)
} }
} }

View File

@ -166,7 +166,7 @@ func (self *sharePublicCommand) run(_ *cobra.Command, args []string) {
p := widgets.NewParagraph() p := widgets.NewParagraph()
p.Border = true p.Border = true
p.Title = " access your zrok service " p.Title = " access your zrok service "
p.Text = fmt.Sprintf("%v%v", strings.Repeat(" ", (((w-12)-len(resp.Payload.FrontendProxyEndpoint))/2)-1), resp.Payload.FrontendProxyEndpoint) p.Text = fmt.Sprintf("%v%v", strings.Repeat(" ", (((w-12)-len(resp.Payload.FrontendProxyEndpoints[0]))/2)-1), resp.Payload.FrontendProxyEndpoints[0])
p.TextStyle = ui.Style{Fg: ui.ColorWhite} p.TextStyle = ui.Style{Fg: ui.ColorWhite}
p.PaddingTop = 1 p.PaddingTop = 1
p.SetRect(5, 5, w-10, 10) p.SetRect(5, 5, w-10, 10)
@ -220,7 +220,7 @@ func (self *sharePublicCommand) run(_ *cobra.Command, args []string) {
} }
} }
} else { } else {
logrus.Infof("access your zrok service: %v", resp.Payload.FrontendProxyEndpoint) logrus.Infof("access your zrok service: %v", resp.Payload.FrontendProxyEndpoints[0])
for { for {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
} }

View File

@ -60,13 +60,18 @@ func (h *shareHandler) Handle(params service.ShareParams, principal *rest_model_
var frontendEndpoints []string var frontendEndpoints []string
switch params.Body.ShareMode { switch params.Body.ShareMode {
case "public": case "public":
if len(params.Body.FrontendSelection) < 1 {
logrus.Info("no frontend selection provided")
return service.NewShareNotFound()
}
var frontendZIds []string var frontendZIds []string
var frontendTemplates []string var frontendTemplates []string
for _, frontendSelection := range params.Body.FrontendSelection { for _, frontendSelection := range params.Body.FrontendSelection {
sfe, err := str.FindFrontendPubliclyNamed(frontendSelection, tx) sfe, err := str.FindFrontendPubliclyNamed(frontendSelection, tx)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return service.NewUpdateShareNotFound() return service.NewShareNotFound()
} }
if sfe != nil && sfe.UrlTemplate != nil { if sfe != nil && sfe.UrlTemplate != nil {
frontendZIds = append(frontendZIds, sfe.ZId) frontendZIds = append(frontendZIds, sfe.ZId)
@ -116,7 +121,7 @@ func (h *shareHandler) Handle(params service.ShareParams, principal *rest_model_
logrus.Infof("recorded service '%v' with id '%v' for '%v'", svcToken, sid, principal.Email) logrus.Infof("recorded service '%v' with id '%v' for '%v'", svcToken, sid, principal.Email)
return service.NewShareCreated().WithPayload(&rest_model_zrok.ShareResponse{ return service.NewShareCreated().WithPayload(&rest_model_zrok.ShareResponse{
FrontendProxyEndpoint: frontendEndpoints[0], FrontendProxyEndpoints: frontendEndpoints,
SvcToken: svcToken, SvcToken: svcToken,
}) })
} }

View File

@ -35,6 +35,12 @@ func (o *ShareReader) ReadResponse(response runtime.ClientResponse, consumer run
return nil, err return nil, err
} }
return nil, result return nil, result
case 404:
result := NewShareNotFound()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500: case 500:
result := NewShareInternalServerError() result := NewShareInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -160,6 +166,57 @@ func (o *ShareUnauthorized) readResponse(response runtime.ClientResponse, consum
return nil return nil
} }
// NewShareNotFound creates a ShareNotFound with default headers values
func NewShareNotFound() *ShareNotFound {
return &ShareNotFound{}
}
/*
ShareNotFound describes a response with status code 404, with default header values.
not found
*/
type ShareNotFound struct {
}
// IsSuccess returns true when this share not found response has a 2xx status code
func (o *ShareNotFound) IsSuccess() bool {
return false
}
// IsRedirect returns true when this share not found response has a 3xx status code
func (o *ShareNotFound) IsRedirect() bool {
return false
}
// IsClientError returns true when this share not found response has a 4xx status code
func (o *ShareNotFound) IsClientError() bool {
return true
}
// IsServerError returns true when this share not found response has a 5xx status code
func (o *ShareNotFound) IsServerError() bool {
return false
}
// IsCode returns true when this share not found response a status code equal to that given
func (o *ShareNotFound) IsCode(code int) bool {
return code == 404
}
func (o *ShareNotFound) Error() string {
return fmt.Sprintf("[POST /share][%d] shareNotFound ", 404)
}
func (o *ShareNotFound) String() string {
return fmt.Sprintf("[POST /share][%d] shareNotFound ", 404)
}
func (o *ShareNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewShareInternalServerError creates a ShareInternalServerError with default headers values // NewShareInternalServerError creates a ShareInternalServerError with default headers values
func NewShareInternalServerError() *ShareInternalServerError { func NewShareInternalServerError() *ShareInternalServerError {
return &ShareInternalServerError{} return &ShareInternalServerError{}

View File

@ -17,8 +17,8 @@ import (
// swagger:model shareResponse // swagger:model shareResponse
type ShareResponse struct { type ShareResponse struct {
// frontend proxy endpoint // frontend proxy endpoints
FrontendProxyEndpoint string `json:"frontendProxyEndpoint,omitempty"` FrontendProxyEndpoints []string `json:"frontendProxyEndpoints"`
// svc token // svc token
SvcToken string `json:"svcToken,omitempty"` SvcToken string `json:"svcToken,omitempty"`

View File

@ -463,6 +463,9 @@ func init() {
"401": { "401": {
"description": "unauthorized" "description": "unauthorized"
}, },
"404": {
"description": "not found"
},
"500": { "500": {
"description": "internal server error", "description": "internal server error",
"schema": { "schema": {
@ -967,8 +970,11 @@ func init() {
"shareResponse": { "shareResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"frontendProxyEndpoint": { "frontendProxyEndpoints": {
"type": "string" "type": "array",
"items": {
"type": "string"
}
}, },
"svcToken": { "svcToken": {
"type": "string" "type": "string"
@ -1502,6 +1508,9 @@ func init() {
"401": { "401": {
"description": "unauthorized" "description": "unauthorized"
}, },
"404": {
"description": "not found"
},
"500": { "500": {
"description": "internal server error", "description": "internal server error",
"schema": { "schema": {
@ -2006,8 +2015,11 @@ func init() {
"shareResponse": { "shareResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"frontendProxyEndpoint": { "frontendProxyEndpoints": {
"type": "string" "type": "array",
"items": {
"type": "string"
}
}, },
"svcToken": { "svcToken": {
"type": "string" "type": "string"

View File

@ -83,6 +83,31 @@ func (o *ShareUnauthorized) WriteResponse(rw http.ResponseWriter, producer runti
rw.WriteHeader(401) rw.WriteHeader(401)
} }
// ShareNotFoundCode is the HTTP code returned for type ShareNotFound
const ShareNotFoundCode int = 404
/*
ShareNotFound not found
swagger:response shareNotFound
*/
type ShareNotFound struct {
}
// NewShareNotFound creates ShareNotFound with default headers values
func NewShareNotFound() *ShareNotFound {
return &ShareNotFound{}
}
// WriteResponse to the client
func (o *ShareNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(404)
}
// ShareInternalServerErrorCode is the HTTP code returned for type ShareInternalServerError // ShareInternalServerErrorCode is the HTTP code returned for type ShareInternalServerError
const ShareInternalServerErrorCode int = 500 const ShareInternalServerErrorCode int = 500

View File

@ -321,6 +321,8 @@ paths:
$ref: "#/definitions/shareResponse" $ref: "#/definitions/shareResponse"
401: 401:
description: unauthorized description: unauthorized
404:
description: not found
500: 500:
description: internal server error description: internal server error
schema: schema:
@ -635,8 +637,10 @@ definitions:
shareResponse: shareResponse:
type: object type: object
properties: properties:
frontendProxyEndpoint: frontendProxyEndpoints:
type: string type: array
items:
type: string
svcToken: svcToken:
type: string type: string

View File

@ -186,7 +186,7 @@
* @typedef shareResponse * @typedef shareResponse
* @memberof module:types * @memberof module:types
* *
* @property {string} frontendProxyEndpoint * @property {string[]} frontendProxyEndpoints
* @property {string} svcToken * @property {string} svcToken
*/ */