more cleanups and polish for sharing and reserving (#122, #41)

This commit is contained in:
Michael Quigley 2022-11-30 14:38:49 -05:00
parent 3f5c5003de
commit 301249fe4a
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
18 changed files with 227 additions and 20 deletions

View File

@ -56,7 +56,10 @@ func (cmd *releaseCommand) run(_ *cobra.Command, args []string) {
Reserved: true, Reserved: true,
} }
if _, err := zrok.Service.Unshare(req, auth); err != nil { if _, err := zrok.Service.Unshare(req, auth); err != nil {
logrus.Errorf("error releasing service '%v': %v", svcToken, err) if !panicInstead {
showError("error releasing service", err)
}
panic(err)
} }
logrus.Infof("reserved service '%v' released", svcToken) logrus.Infof("reserved service '%v' released", svcToken)

View File

@ -41,7 +41,7 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
showError("invalid sharing mode; expecting 'public' or 'private'", nil) showError("invalid sharing mode; expecting 'public' or 'private'", nil)
} }
targetEndpoint, err := url.Parse(args[0]) targetEndpoint, err := url.Parse(args[1])
if err != nil { if err != nil {
if !panicInstead { if !panicInstead {
showError("invalid target endpoint URL", err) showError("invalid target endpoint URL", err)

129
cmd/zrok/share_reserved.go Normal file
View File

@ -0,0 +1,129 @@
package main
import (
ui "github.com/gizak/termui/v3"
httptransport "github.com/go-openapi/runtime/client"
"github.com/openziti-test-kitchen/zrok/endpoints/backend"
"github.com/openziti-test-kitchen/zrok/rest_client_zrok/service"
"github.com/openziti-test-kitchen/zrok/rest_model_zrok"
"github.com/openziti-test-kitchen/zrok/zrokdir"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net/url"
"time"
)
func init() {
shareCmd.AddCommand(newShareReservedCommand().cmd)
}
type shareReservedCommand struct {
overrideEndpoint string
cmd *cobra.Command
}
func newShareReservedCommand() *shareReservedCommand {
cmd := &cobra.Command{
Use: "reserved <serviceToken>",
}
command := &shareReservedCommand{cmd: cmd}
cmd.Flags().StringVar(&command.overrideEndpoint, "override-endpoint", "", "Override the stored target endpoint with a replacement")
cmd.Run = command.run
return command
}
func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
svcToken := args[0]
targetEndpoint := ""
if cmd.overrideEndpoint != "" {
e, err := url.Parse(cmd.overrideEndpoint)
if err != nil {
if !panicInstead {
showError("invalid override endpoint URL", err)
}
panic(err)
}
if e.Scheme == "" {
e.Scheme = "https"
}
targetEndpoint = e.String()
}
env, err := zrokdir.LoadEnvironment()
if err != nil {
ui.Close()
if !panicInstead {
showError("unable to load environment; did you 'zrok enable'?", err)
}
panic(err)
}
zrok, err := zrokdir.ZrokClient(env.ApiEndpoint)
if err != nil {
ui.Close()
if !panicInstead {
showError("unable to create zrok client", err)
}
panic(err)
}
auth := httptransport.APIKeyAuth("X-TOKEN", "header", env.Token)
req := service.NewGetServiceParams()
req.Body = &rest_model_zrok.ServiceRequest{
EnvZID: env.ZId,
SvcToken: svcToken,
}
resp, err := zrok.Service.GetService(req, auth)
if err != nil {
if !panicInstead {
showError("unable to retrieve reserved service", err)
}
panic(err)
}
if targetEndpoint == "" {
targetEndpoint = resp.Payload.BackendProxyEndpoint
}
zif, err := zrokdir.ZitiIdentityFile("backend")
if err != nil {
ui.Close()
if !panicInstead {
showError("unable to load ziti identity configuration", err)
}
panic(err)
}
cfg := &backend.Config{
IdentityPath: zif,
EndpointAddress: targetEndpoint,
Service: svcToken,
}
logrus.Infof("sharing target endpoint: '%v'", cfg.EndpointAddress)
httpProxy, err := backend.NewHTTP(cfg)
if err != nil {
ui.Close()
if !panicInstead {
showError("unable to create http backend", err)
}
panic(err)
}
go func() {
if err := httpProxy.Run(); err != nil {
if !panicInstead {
showError("unable to run http proxy", err)
}
panic(err)
}
}()
switch resp.Payload.ShareMode {
case "public":
logrus.Infof("access your zrok service: %v", resp.Payload.FrontendEndpoint)
case "private":
logrus.Infof("use this command to access your zrok service: 'zrok access private %v'", svcToken)
}
for {
time.Sleep(30 * time.Second)
}
}

View File

@ -8,6 +8,7 @@ import (
"github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations" "github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations"
"github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/account" "github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/account"
"github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/metadata" "github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/metadata"
"github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/service"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -35,6 +36,7 @@ func Run(inCfg *Config) error {
api.MetadataOverviewHandler = metadata.OverviewHandlerFunc(overviewHandler) api.MetadataOverviewHandler = metadata.OverviewHandlerFunc(overviewHandler)
api.MetadataVersionHandler = metadata.VersionHandlerFunc(versionHandler) api.MetadataVersionHandler = metadata.VersionHandlerFunc(versionHandler)
api.ServiceAccessHandler = newAccessHandler() api.ServiceAccessHandler = newAccessHandler()
api.ServiceGetServiceHandler = service.GetServiceHandlerFunc(getServiceHandler)
api.ServiceShareHandler = newShareHandler() api.ServiceShareHandler = newShareHandler()
api.ServiceUnaccessHandler = newUnaccessHandler() api.ServiceUnaccessHandler = newUnaccessHandler()
api.ServiceUnshareHandler = newUnshareHandler() api.ServiceUnshareHandler = newUnshareHandler()

61
controller/get_service.go Normal file
View File

@ -0,0 +1,61 @@
package controller
import (
"github.com/go-openapi/runtime/middleware"
"github.com/openziti-test-kitchen/zrok/rest_model_zrok"
"github.com/openziti-test-kitchen/zrok/rest_server_zrok/operations/service"
"github.com/sirupsen/logrus"
)
func getServiceHandler(params service.GetServiceParams, principal *rest_model_zrok.Principal) middleware.Responder {
envZId := params.Body.EnvZID
svcToken := params.Body.SvcToken
tx, err := str.Begin()
if err != nil {
logrus.Errorf("error starting transaction: %v", err)
return service.NewGetServiceInternalServerError()
}
defer func() { _ = tx.Rollback() }()
ssvc, err := str.FindServiceWithToken(svcToken, tx)
if err != nil {
logrus.Errorf("error finding service with token '%v': %v", svcToken, err)
return service.NewGetServiceNotFound()
}
senvs, err := str.FindEnvironmentsForAccount(int(principal.ID), tx)
if err != nil {
logrus.Errorf("error listing environments for account '%v': %v", principal.Email, err)
return service.NewGetServiceInternalServerError()
}
envFound := false
for _, senv := range senvs {
if senv.Id == ssvc.EnvironmentId && senv.ZId == envZId {
envFound = true
break
}
}
if !envFound {
logrus.Errorf("service '%v' not in environment '%v'", svcToken, envZId)
return service.NewGetServiceNotFound()
}
svc := &rest_model_zrok.Service03{
Token: ssvc.Token,
ZID: ssvc.ZId,
ShareMode: ssvc.ShareMode,
BackendMode: ssvc.BackendMode,
Reserved: ssvc.Reserved,
}
if ssvc.FrontendSelection != nil {
svc.FrontendSelection = *ssvc.FrontendSelection
}
if ssvc.FrontendEndpoint != nil {
svc.FrontendEndpoint = *ssvc.FrontendEndpoint
}
if ssvc.BackendProxyEndpoint != nil {
svc.BackendProxyEndpoint = *ssvc.BackendProxyEndpoint
}
return service.NewGetServiceOK().WithPayload(svc)
}

View File

@ -34,9 +34,9 @@ func (str *Store) GetFrontend(id int, tx *sqlx.Tx) (*Frontend, error) {
return i, nil return i, nil
} }
func (str *Store) FindFrontendNamed(name string, tx *sqlx.Tx) (*Frontend, error) { func (str *Store) FindFrontendWithToken(token string, tx *sqlx.Tx) (*Frontend, error) {
i := &Frontend{} i := &Frontend{}
if err := tx.QueryRowx("select frontends.* from frontends where name = $1", name).StructScan(i); err != nil { if err := tx.QueryRowx("select frontends.* from frontends where token = $1", token).StructScan(i); err != nil {
return nil, errors.Wrap(err, "error selecting frontend by name") return nil, errors.Wrap(err, "error selecting frontend by name")
} }
return i, nil return i, nil

View File

@ -51,7 +51,7 @@ func TestPublicFrontend(t *testing.T) {
err = str.DeleteFrontend(fe.Id, tx) err = str.DeleteFrontend(fe.Id, tx)
assert.Nil(t, err) assert.Nil(t, err)
fe0, err = str.FindFrontendNamed(feName, tx) fe0, err = str.FindFrontendWithToken(feName, tx)
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Nil(t, fe0) assert.Nil(t, fe0)

View File

@ -4,7 +4,7 @@ create table frontends (
id serial primary key, id serial primary key,
environment_id integer not null references environments(id), environment_id integer not null references environments(id),
token varchar(32) not null unique, token varchar(32) not null unique,
z_id varchar(32) not null unique, z_id varchar(32) not null,
public_name varchar(64) unique, public_name varchar(64) unique,
reserved boolean not null default(false), reserved boolean not null default(false),
created_at timestamptz not null default(current_timestamp), created_at timestamptz not null default(current_timestamp),

View File

@ -21,7 +21,7 @@ create table frontends (
id integer primary key, id integer primary key,
environment_id integer not null references environments(id), environment_id integer not null references environments(id),
token varchar(32) not null unique, token varchar(32) not null unique,
z_id varchar(32) not null unique, z_id varchar(32) not null,
public_name varchar(64) unique, public_name varchar(64) unique,
reserved boolean not null default(false), reserved boolean not null default(false),
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),

View File

@ -53,7 +53,7 @@ func (h *unaccessHandler) Handle(params service.UnaccessParams, principal *rest_
return service.NewUnaccessUnauthorized() return service.NewUnaccessUnauthorized()
} }
sfe, err := str.FindFrontendNamed(feToken, tx) sfe, err := str.FindFrontendWithToken(feToken, tx)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return service.NewUnaccessInternalServerError() return service.NewUnaccessInternalServerError()

View File

@ -37,7 +37,7 @@ func (h *unshareHandler) Handle(params service.UnshareParams, principal *rest_mo
svcZId, err := h.findServiceZId(svcToken, edge) svcZId, err := h.findServiceZId(svcToken, edge)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
return service.NewUnshareInternalServerError() return service.NewUnshareNotFound()
} }
var senv *store.Environment var senv *store.Environment
if envs, err := str.FindEnvironmentsForAccount(int(principal.ID), tx); err == nil { if envs, err := str.FindEnvironmentsForAccount(int(principal.ID), tx); err == nil {
@ -54,7 +54,7 @@ func (h *unshareHandler) Handle(params service.UnshareParams, principal *rest_mo
} }
} else { } else {
logrus.Errorf("error finding environments for account '%v': %v", principal.Email, err) logrus.Errorf("error finding environments for account '%v': %v", principal.Email, err)
return service.NewUnshareInternalServerError() return service.NewUnshareNotFound()
} }
var ssvc *store.Service var ssvc *store.Service

View File

@ -63,7 +63,7 @@ GetServiceOK describes a response with status code 200, with default header valu
ok ok
*/ */
type GetServiceOK struct { type GetServiceOK struct {
Payload *rest_model_zrok.Service Payload *rest_model_zrok.Service03
} }
// IsSuccess returns true when this get service o k response has a 2xx status code // IsSuccess returns true when this get service o k response has a 2xx status code
@ -99,13 +99,13 @@ func (o *GetServiceOK) String() string {
return fmt.Sprintf("[GET /service][%d] getServiceOK %+v", 200, o.Payload) return fmt.Sprintf("[GET /service][%d] getServiceOK %+v", 200, o.Payload)
} }
func (o *GetServiceOK) GetPayload() *rest_model_zrok.Service { func (o *GetServiceOK) GetPayload() *rest_model_zrok.Service03 {
return o.Payload return o.Payload
} }
func (o *GetServiceOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetServiceOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(rest_model_zrok.Service) o.Payload = new(rest_model_zrok.Service03)
// response payload // response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {

View File

@ -17,6 +17,9 @@ import (
// swagger:model serviceRequest // swagger:model serviceRequest
type ServiceRequest struct { type ServiceRequest struct {
// env z Id
EnvZID string `json:"envZId,omitempty"`
// svc token // svc token
SvcToken string `json:"svcToken,omitempty"` SvcToken string `json:"svcToken,omitempty"`
} }

View File

@ -284,7 +284,7 @@ func init() {
"200": { "200": {
"description": "ok", "description": "ok",
"schema": { "schema": {
"$ref": "#/definitions/service" "$ref": "#/definitions/service03"
} }
}, },
"401": { "401": {
@ -693,6 +693,9 @@ func init() {
"serviceRequest": { "serviceRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"envZId": {
"type": "string"
},
"svcToken": { "svcToken": {
"type": "string" "type": "string"
} }
@ -1082,7 +1085,7 @@ func init() {
"200": { "200": {
"description": "ok", "description": "ok",
"schema": { "schema": {
"$ref": "#/definitions/service" "$ref": "#/definitions/service03"
} }
}, },
"401": { "401": {
@ -1491,6 +1494,9 @@ func init() {
"serviceRequest": { "serviceRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"envZId": {
"type": "string"
},
"svcToken": { "svcToken": {
"type": "string" "type": "string"
} }

View File

@ -26,7 +26,7 @@ type GetServiceOK struct {
/* /*
In: Body In: Body
*/ */
Payload *rest_model_zrok.Service `json:"body,omitempty"` Payload *rest_model_zrok.Service03 `json:"body,omitempty"`
} }
// NewGetServiceOK creates GetServiceOK with default headers values // NewGetServiceOK creates GetServiceOK with default headers values
@ -36,13 +36,13 @@ func NewGetServiceOK() *GetServiceOK {
} }
// WithPayload adds the payload to the get service o k response // WithPayload adds the payload to the get service o k response
func (o *GetServiceOK) WithPayload(payload *rest_model_zrok.Service) *GetServiceOK { func (o *GetServiceOK) WithPayload(payload *rest_model_zrok.Service03) *GetServiceOK {
o.Payload = payload o.Payload = payload
return o return o
} }
// SetPayload sets the payload to the get service o k response // SetPayload sets the payload to the get service o k response
func (o *GetServiceOK) SetPayload(payload *rest_model_zrok.Service) { func (o *GetServiceOK) SetPayload(payload *rest_model_zrok.Service03) {
o.Payload = payload o.Payload = payload
} }

View File

@ -211,7 +211,7 @@ paths:
200: 200:
description: ok description: ok
schema: schema:
$ref: "#/definitions/service" $ref: "#/definitions/service03"
401: 401:
description: unauthorized description: unauthorized
404: 404:
@ -465,6 +465,8 @@ definitions:
serviceRequest: serviceRequest:
type: object type: object
properties: properties:
envZId:
type: string
svcToken: svcToken:
type: string type: string

View File

@ -20,7 +20,7 @@ export function access(options) {
/** /**
* @param {object} options Optional options * @param {object} options Optional options
* @param {module:types.serviceRequest} [options.body] * @param {module:types.serviceRequest} [options.body]
* @return {Promise<module:types.service>} ok * @return {Promise<module:types.service03>} ok
*/ */
export function getService(options) { export function getService(options) {
if (!options) options = {} if (!options) options = {}

View File

@ -138,6 +138,7 @@
* @typedef serviceRequest * @typedef serviceRequest
* @memberof module:types * @memberof module:types
* *
* @property {string} envZId
* @property {string} svcToken * @property {string} svcToken
*/ */